diff --git a/api4/bot.go b/api4/bot.go index 62c2bc38cf..6c45909717 100644 --- a/api4/bot.go +++ b/api4/bot.go @@ -39,7 +39,7 @@ func createBot(c *Context, w http.ResponseWriter, r *http.Request) { auditRec := c.MakeAuditRecord("createBot", audit.Fail) defer c.LogAuditRec(auditRec) - auditRec.AddEventParameter("bot", bot) + audit.AddEventParameterAuditable(auditRec, "bot", bot) if !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PermissionCreateBot) { c.SetPermissionError(model.PermissionCreateBot) @@ -90,8 +90,8 @@ func patchBot(c *Context, w http.ResponseWriter, r *http.Request) { auditRec := c.MakeAuditRecord("patchBot", audit.Fail) defer c.LogAuditRec(auditRec) - auditRec.AddEventParameter("id", botUserId) - auditRec.AddEventParameter("bot", botPatch) + audit.AddEventParameter(auditRec, "id", botUserId) + audit.AddEventParameterAuditable(auditRec, "bot", botPatch) if err := c.App.SessionHasPermissionToManageBot(*c.AppContext.Session(), botUserId); err != nil { c.Err = err @@ -208,8 +208,8 @@ func updateBotActive(c *Context, w http.ResponseWriter, active bool) { auditRec := c.MakeAuditRecord("updateBotActive", audit.Fail) defer c.LogAuditRec(auditRec) - auditRec.AddEventParameter("id", botUserId) - auditRec.AddEventParameter("enable", active) + audit.AddEventParameter(auditRec, "id", botUserId) + audit.AddEventParameter(auditRec, "enable", active) if err := c.App.SessionHasPermissionToManageBot(*c.AppContext.Session(), botUserId); err != nil { c.Err = err @@ -242,8 +242,8 @@ func assignBot(c *Context, w http.ResponseWriter, _ *http.Request) { auditRec := c.MakeAuditRecord("assignBot", audit.Fail) defer c.LogAuditRec(auditRec) - auditRec.AddEventParameter("id", botUserId) - auditRec.AddEventParameter("user_id", userId) + audit.AddEventParameter(auditRec, "id", botUserId) + audit.AddEventParameter(auditRec, "user_id", userId) if err := c.App.SessionHasPermissionToManageBot(*c.AppContext.Session(), botUserId); err != nil { c.Err = err @@ -295,9 +295,9 @@ func convertBotToUser(c *Context, w http.ResponseWriter, r *http.Request) { auditRec := c.MakeAuditRecord("convertBotToUser", audit.Fail) defer c.LogAuditRec(auditRec) - auditRec.AddEventParameter("bot", bot) - auditRec.AddEventParameter("userPatch", userPatch) - auditRec.AddEventParameter("set_system_admin", systemAdmin) + audit.AddEventParameterAuditable(auditRec, "bot", bot) + audit.AddEventParameterAuditable(auditRec, "user_patch", &userPatch) + audit.AddEventParameter(auditRec, "set_system_admin", systemAdmin) if !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PermissionManageSystem) { c.SetPermissionError(model.PermissionManageSystem) diff --git a/api4/channel.go b/api4/channel.go index 0edcd0eaf9..0705d26948 100644 --- a/api4/channel.go +++ b/api4/channel.go @@ -88,7 +88,7 @@ func createChannel(c *Context, w http.ResponseWriter, r *http.Request) { auditRec := c.MakeAuditRecord("createChannel", audit.Fail) defer c.LogAuditRec(auditRec) - auditRec.AddEventParameter("channel", channel) + audit.AddEventParameterAuditable(auditRec, "channel", channel) if channel.Type == model.ChannelTypeOpen && !c.App.SessionHasPermissionToTeam(*c.AppContext.Session(), channel.TeamId, model.PermissionCreatePublicChannel) { c.SetPermissionError(model.PermissionCreatePublicChannel) @@ -137,7 +137,7 @@ func updateChannel(c *Context, w http.ResponseWriter, r *http.Request) { } auditRec := c.MakeAuditRecord("updateChannel", audit.Fail) - auditRec.AddEventParameter("channel", channel) + audit.AddEventParameterAuditable(auditRec, "channel", channel) defer c.LogAuditRec(auditRec) originalOldChannel, appErr := c.App.GetChannel(c.AppContext, channel.Id) @@ -202,7 +202,7 @@ func updateChannel(c *Context, w http.ResponseWriter, r *http.Request) { if channel.Name != "" { oldChannel.Name = channel.Name - auditRec.AddMeta("new_channel_name", oldChannel.Name) + audit.AddEventParameter(auditRec, "new_channel_name", oldChannel.Name) } if channel.GroupConstrained != nil { @@ -214,7 +214,6 @@ func updateChannel(c *Context, w http.ResponseWriter, r *http.Request) { c.Err = appErr return } - auditRec.AddMeta("update", updatedChannel) if oldChannelDisplayName != channel.DisplayName { if err := c.App.PostUpdateChannelDisplayNameMessage(c.AppContext, c.AppContext.Session().UserId, channel, oldChannelDisplayName, channel.DisplayName); err != nil { @@ -238,6 +237,10 @@ func updateChannelPrivacy(c *Context, w http.ResponseWriter, r *http.Request) { return } + auditRec := c.MakeAuditRecord("updateChannelPrivacy", audit.Fail) + audit.AddEventParameter(auditRec, "channel_id", c.Params.ChannelId) + defer c.LogAuditRec(auditRec) + props := model.StringInterfaceFromJSON(r.Body) privacy, ok := props["privacy"].(string) if !ok || (model.ChannelType(privacy) != model.ChannelTypeOpen && model.ChannelType(privacy) != model.ChannelTypePrivate) { @@ -245,15 +248,14 @@ func updateChannelPrivacy(c *Context, w http.ResponseWriter, r *http.Request) { return } + audit.AddEventParameter(auditRec, "privacy", privacy) + channel, err := c.App.GetChannel(c.AppContext, c.Params.ChannelId) if err != nil { c.Err = err return } - auditRec := c.MakeAuditRecord("updateChannelPrivacy", audit.Fail) - defer c.LogAuditRec(auditRec) - auditRec.AddEventParameter("props", props) auditRec.AddEventPriorState(channel) if model.ChannelType(privacy) == model.ChannelTypeOpen && !c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), c.Params.ChannelId, model.PermissionConvertPrivateChannelToPublic) { @@ -316,7 +318,7 @@ func patchChannel(c *Context, w http.ResponseWriter, r *http.Request) { auditRec := c.MakeAuditRecord("patchChannel", audit.Fail) defer c.LogAuditRec(auditRec) - auditRec.AddEventParameter("channel", patch) + audit.AddEventParameterAuditable(auditRec, "channel", patch) auditRec.AddEventPriorState(oldChannel) switch oldChannel.Type { @@ -431,7 +433,7 @@ func createDirectChannel(c *Context, w http.ResponseWriter, r *http.Request) { } auditRec := c.MakeAuditRecord("createDirectChannel", audit.Fail) - auditRec.AddEventParameter("user_ids", userIds) + audit.AddEventParameter(auditRec, "user_ids", userIds) defer c.LogAuditRec(auditRec) if !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PermissionCreateDirectChannel) { @@ -449,7 +451,7 @@ func createDirectChannel(c *Context, w http.ResponseWriter, r *http.Request) { otherUserId = userIds[1] } - auditRec.AddEventParameter("user_id", otherUserId) + audit.AddEventParameter(auditRec, "user_id", otherUserId) canSee, err := c.App.UserCanSeeOtherUser(c.AppContext.Session().UserId, otherUserId) if err != nil { @@ -521,7 +523,7 @@ func createGroupChannel(c *Context, w http.ResponseWriter, r *http.Request) { } auditRec := c.MakeAuditRecord("createGroupChannel", audit.Fail) - auditRec.AddEventParameter("user_ids", userIds) + audit.AddEventParameter(auditRec, "user_ids", userIds) defer c.LogAuditRec(auditRec) if !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PermissionCreateGroupChannel) { @@ -1230,7 +1232,7 @@ func deleteChannel(c *Context, w http.ResponseWriter, r *http.Request) { } auditRec := c.MakeAuditRecord("deleteChannel", audit.Fail) - auditRec.AddEventParameter("id", c.Params.ChannelId) + audit.AddEventParameter(auditRec, "id", c.Params.ChannelId) auditRec.AddEventPriorState(channel) defer c.LogAuditRec(auditRec) @@ -1527,8 +1529,8 @@ func updateChannelMemberRoles(c *Context, w http.ResponseWriter, r *http.Request auditRec := c.MakeAuditRecord("updateChannelMemberRoles", audit.Fail) defer c.LogAuditRec(auditRec) - auditRec.AddEventParameter("props", props) - auditRec.AddEventParameter("channel_id", c.Params.ChannelId) + audit.AddEventParameter(auditRec, "props", props) + audit.AddEventParameter(auditRec, "channel_id", c.Params.ChannelId) if !c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), c.Params.ChannelId, model.PermissionManageChannelRoles) { c.SetPermissionError(model.PermissionManageChannelRoles) @@ -1559,8 +1561,8 @@ func updateChannelMemberSchemeRoles(c *Context, w http.ResponseWriter, r *http.R auditRec := c.MakeAuditRecord("updateChannelMemberSchemeRoles", audit.Fail) defer c.LogAuditRec(auditRec) - auditRec.AddEventParameter("channel_id", c.Params.ChannelId) - auditRec.AddEventParameter("roles", schemeRoles) + audit.AddEventParameter(auditRec, "channel_id", c.Params.ChannelId) + audit.AddEventParameterAuditable(auditRec, "roles", &schemeRoles) if !c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), c.Params.ChannelId, model.PermissionManageChannelRoles) { c.SetPermissionError(model.PermissionManageChannelRoles) @@ -1591,8 +1593,8 @@ func updateChannelMemberNotifyProps(c *Context, w http.ResponseWriter, r *http.R auditRec := c.MakeAuditRecord("updateChannelMemberNotifyProps", audit.Fail) defer c.LogAuditRec(auditRec) - auditRec.AddEventParameter("channel_id", c.Params.ChannelId) - auditRec.AddEventParameter("props", props) + audit.AddEventParameter(auditRec, "channel_id", c.Params.ChannelId) + audit.AddEventParameter(auditRec, "props", props) if !c.App.SessionHasPermissionToUser(*c.AppContext.Session(), c.Params.UserId) { c.SetPermissionError(model.PermissionEditOtherUsers) @@ -1625,7 +1627,8 @@ func addChannelMember(c *Context, w http.ResponseWriter, r *http.Request) { auditRec := c.MakeAuditRecord("addChannelMember", audit.Fail) defer c.LogAuditRec(auditRec) - auditRec.AddEventParameter("props", props) + audit.AddEventParameter(auditRec, "user_id", userId) + audit.AddEventParameter(auditRec, "channel_id", c.Params.ChannelId) member := &model.ChannelMember{ ChannelId: c.Params.ChannelId, @@ -1638,6 +1641,8 @@ func addChannelMember(c *Context, w http.ResponseWriter, r *http.Request) { return } + audit.AddEventParameter(auditRec, "post_root_id", postRootId) + if ok && len(postRootId) == 26 { rootPost, err := c.App.GetSinglePost(postRootId, false) if err != nil { @@ -1656,8 +1661,6 @@ func addChannelMember(c *Context, w http.ResponseWriter, r *http.Request) { return } - auditRec.AddEventParameter("channel_id", member.ChannelId) - if channel.Type == model.ChannelTypeDirect || channel.Type == model.ChannelTypeGroup { c.Err = model.NewAppError("addUserToChannel", "api.channel.add_user_to_channel.type.app_error", nil, "", http.StatusBadRequest) return @@ -1758,6 +1761,11 @@ func removeChannelMember(c *Context, w http.ResponseWriter, r *http.Request) { return } + auditRec := c.MakeAuditRecord("removeChannelMember", audit.Fail) + defer c.LogAuditRec(auditRec) + audit.AddEventParameter(auditRec, "channel_id", c.Params.ChannelId) + audit.AddEventParameter(auditRec, "user_id", c.Params.UserId) + channel, err := c.App.GetChannel(c.AppContext, c.Params.ChannelId) if err != nil { c.Err = err @@ -1770,11 +1778,6 @@ func removeChannelMember(c *Context, w http.ResponseWriter, r *http.Request) { return } - auditRec := c.MakeAuditRecord("removeChannelMember", audit.Fail) - defer c.LogAuditRec(auditRec) - auditRec.AddEventParameter("channel_id", channel.Id) - auditRec.AddEventParameter("user_id", user.Id) - if !(channel.Type == model.ChannelTypeOpen || channel.Type == model.ChannelTypePrivate) { c.Err = model.NewAppError("removeChannelMember", "api.channel.remove_channel_member.type.app_error", nil, "", http.StatusBadRequest) return @@ -1814,6 +1817,10 @@ func updateChannelScheme(c *Context, w http.ResponseWriter, r *http.Request) { return } + auditRec := c.MakeAuditRecord("updateChannelScheme", audit.Fail) + audit.AddEventParameter(auditRec, "channel_id", c.Params.ChannelId) + defer c.LogAuditRec(auditRec) + var p model.SchemeIDPatch if jsonErr := json.NewDecoder(r.Body).Decode(&p); jsonErr != nil || p.SchemeID == nil || !model.IsValidId(*p.SchemeID) { c.SetInvalidParamWithErr("scheme_id", jsonErr) @@ -1821,9 +1828,7 @@ func updateChannelScheme(c *Context, w http.ResponseWriter, r *http.Request) { } schemeID := p.SchemeID - auditRec := c.MakeAuditRecord("updateChannelScheme", audit.Fail) - defer c.LogAuditRec(auditRec) - auditRec.AddEventParameter("scheme_id", *schemeID) + audit.AddEventParameter(auditRec, "scheme_id", *schemeID) if c.App.Channels().License() == nil { c.Err = model.NewAppError("Api4.UpdateChannelScheme", "api.channel.update_channel_scheme.license.error", nil, "", http.StatusForbidden) @@ -2014,7 +2019,7 @@ func patchChannelModerations(c *Context, w http.ResponseWriter, r *http.Request) c.Err = appErr return } - auditRec.AddMeta("channel", channel) + audit.AddEventParameterAuditable(auditRec, "channel", channel) var channelModerationsPatch []*model.ChannelModerationPatch err := json.NewDecoder(r.Body).Decode(&channelModerationsPatch) @@ -2028,7 +2033,7 @@ func patchChannelModerations(c *Context, w http.ResponseWriter, r *http.Request) c.Err = appErr return } - auditRec.AddEventParameter("patch", channelModerationsPatch) + audit.AddEventParameterAuditableArray(auditRec, "channel_moderations_patch", channelModerationsPatch) b, err := json.Marshal(channelModerations) if err != nil { @@ -2073,8 +2078,9 @@ func moveChannel(c *Context, w http.ResponseWriter, r *http.Request) { auditRec := c.MakeAuditRecord("moveChannel", audit.Fail) defer c.LogAuditRec(auditRec) - auditRec.AddEventParameter("channel_id", c.Params.ChannelId) - auditRec.AddEventParameter("props", props) + audit.AddEventParameter(auditRec, "channel_id", c.Params.ChannelId) + audit.AddEventParameter(auditRec, "team_id", teamId) + audit.AddEventParameter(auditRec, "force", force) auditRec.AddEventPriorState(channel) // TODO check and verify if the below three things are parameters or prior state if any diff --git a/api4/channel_local.go b/api4/channel_local.go index 0c5da46a6c..83634a6116 100644 --- a/api4/channel_local.go +++ b/api4/channel_local.go @@ -47,7 +47,7 @@ func localCreateChannel(c *Context, w http.ResponseWriter, r *http.Request) { auditRec := c.MakeAuditRecord("localCreateChannel", audit.Fail) defer c.LogAuditRec(auditRec) - auditRec.AddEventParameter("channel", channel) + audit.AddEventParameterAuditable(auditRec, "channel", channel) sc, appErr := c.App.CreateChannel(c.AppContext, channel, false) if appErr != nil { @@ -87,7 +87,7 @@ func localUpdateChannelPrivacy(c *Context, w http.ResponseWriter, r *http.Reques auditRec := c.MakeAuditRecord("localUpdateChannelPrivacy", audit.Fail) defer c.LogAuditRec(auditRec) - auditRec.AddEventParameter("props", props) + audit.AddEventParameter(auditRec, "privacy", privacy) if channel.Name == model.DefaultChannelName && model.ChannelType(privacy) == model.ChannelTypePrivate { c.Err = model.NewAppError("updateChannelPrivacy", "api.channel.update_channel_privacy.default_channel_error", nil, "", http.StatusBadRequest) @@ -125,7 +125,7 @@ func localRestoreChannel(c *Context, w http.ResponseWriter, r *http.Request) { auditRec := c.MakeAuditRecord("localRestoreChannel", audit.Fail) defer c.LogAuditRec(auditRec) - auditRec.AddEventParameter("channel_id", c.Params.ChannelId) + audit.AddEventParameter(auditRec, "channel_id", c.Params.ChannelId) channel, err = c.App.RestoreChannel(c.AppContext, channel, "") if err != nil { @@ -149,6 +149,10 @@ func localAddChannelMember(c *Context, w http.ResponseWriter, r *http.Request) { return } + auditRec := c.MakeAuditRecord("localAddChannelMember", audit.Fail) + audit.AddEventParameter(auditRec, "channel_id", c.Params.ChannelId) + defer c.LogAuditRec(auditRec) + props := model.StringInterfaceFromJSON(r.Body) userId, ok := props["user_id"].(string) if !ok || !model.IsValidId(userId) { @@ -156,6 +160,8 @@ func localAddChannelMember(c *Context, w http.ResponseWriter, r *http.Request) { return } + audit.AddEventParameter(auditRec, "user_id", userId) + member := &model.ChannelMember{ ChannelId: c.Params.ChannelId, UserId: userId, @@ -167,6 +173,8 @@ func localAddChannelMember(c *Context, w http.ResponseWriter, r *http.Request) { return } + audit.AddEventParameter(auditRec, "post_root_id", postRootId) + if ok && len(postRootId) == 26 { rootPost, err := c.App.GetSinglePost(postRootId, false) if err != nil { @@ -185,10 +193,7 @@ func localAddChannelMember(c *Context, w http.ResponseWriter, r *http.Request) { return } - auditRec := c.MakeAuditRecord("localAddChannelMember", audit.Fail) - auditRec.AddEventParameter("props", props) - defer c.LogAuditRec(auditRec) - auditRec.AddMeta("channel", channel) + audit.AddEventParameterAuditable(auditRec, "channel", channel) if channel.Type == model.ChannelTypeDirect || channel.Type == model.ChannelTypeGroup { c.Err = model.NewAppError("localAddChannelMember", "api.channel.add_user_to_channel.type.app_error", nil, "", http.StatusBadRequest) @@ -261,8 +266,8 @@ func localRemoveChannelMember(c *Context, w http.ResponseWriter, r *http.Request auditRec := c.MakeAuditRecord("localRemoveChannelMember", audit.Fail) defer c.LogAuditRec(auditRec) - auditRec.AddEventParameter("channel_id", c.Params.ChannelId) - auditRec.AddEventParameter("remove_user_id", c.Params.UserId) + audit.AddEventParameter(auditRec, "channel_id", c.Params.ChannelId) + audit.AddEventParameter(auditRec, "remove_user_id", c.Params.UserId) if err = c.App.RemoveUserFromChannel(c.AppContext, c.Params.UserId, "", channel); err != nil { c.Err = err @@ -297,7 +302,7 @@ func localPatchChannel(c *Context, w http.ResponseWriter, r *http.Request) { auditRec := c.MakeAuditRecord("localPatchChannel", audit.Fail) defer c.LogAuditRec(auditRec) - auditRec.AddEventParameter("channel_patch", patch) + audit.AddEventParameterAuditable(auditRec, "channel_patch", patch) channel.Patch(patch) rchannel, appErr := c.App.UpdateChannel(c.AppContext, channel) @@ -355,7 +360,8 @@ func localMoveChannel(c *Context, w http.ResponseWriter, r *http.Request) { auditRec := c.MakeAuditRecord("localMoveChannel", audit.Fail) defer c.LogAuditRec(auditRec) - auditRec.AddEventParameter("props", props) + audit.AddEventParameter(auditRec, "team_id", teamId) + audit.AddEventParameter(auditRec, "force", force) // TODO do we need these? auditRec.AddMeta("channel_id", channel.Id) @@ -413,8 +419,8 @@ func localDeleteChannel(c *Context, w http.ResponseWriter, r *http.Request) { auditRec := c.MakeAuditRecord("localDeleteChannel", audit.Fail) defer c.LogAuditRec(auditRec) - auditRec.AddMeta("channeld", channel) - auditRec.AddEventParameter("channel_id", c.Params.ChannelId) + auditRec.AddEventPriorState(channel) + audit.AddEventParameter(auditRec, "channel_id", c.Params.ChannelId) if channel.Type == model.ChannelTypeDirect || channel.Type == model.ChannelTypeGroup { c.Err = model.NewAppError("localDeleteChannel", "api.channel.delete_channel.type.invalid", nil, "", http.StatusBadRequest) diff --git a/api4/command.go b/api4/command.go index 1025424c83..1f7d08dd38 100644 --- a/api4/command.go +++ b/api4/command.go @@ -37,7 +37,7 @@ func createCommand(c *Context, w http.ResponseWriter, r *http.Request) { } auditRec := c.MakeAuditRecord("createCommand", audit.Fail) - auditRec.AddEventParameter("command", cmd) + audit.AddEventParameterAuditable(auditRec, "command", &cmd) defer c.LogAuditRec(auditRec) c.LogAudit("attempt") @@ -56,7 +56,6 @@ func createCommand(c *Context, w http.ResponseWriter, r *http.Request) { auditRec.Success() c.LogAudit("success") - auditRec.AddMeta("command", rcmd) auditRec.AddEventResultState(rcmd) auditRec.AddEventObjectType("command") @@ -79,17 +78,17 @@ func updateCommand(c *Context, w http.ResponseWriter, r *http.Request) { } auditRec := c.MakeAuditRecord("updateCommand", audit.Fail) - auditRec.AddEventParameter("command", cmd) + audit.AddEventParameterAuditable(auditRec, "command", &cmd) defer c.LogAuditRec(auditRec) c.LogAudit("attempt") oldCmd, err := c.App.GetCommand(c.Params.CommandId) if err != nil { - auditRec.AddMeta("command_id", c.Params.CommandId) + audit.AddEventParameter(auditRec, "command_id", c.Params.CommandId) c.SetCommandNotFoundError() return } - auditRec.AddMeta("command", oldCmd) + auditRec.AddEventPriorState(oldCmd) if cmd.TeamId != oldCmd.TeamId { c.Err = model.NewAppError("updateCommand", "api.command.team_mismatch.app_error", nil, "user_id="+c.AppContext.Session().UserId, http.StatusBadRequest) @@ -139,7 +138,7 @@ func moveCommand(c *Context, w http.ResponseWriter, r *http.Request) { } auditRec := c.MakeAuditRecord("moveCommand", audit.Fail) - auditRec.AddEventParameter("command_move_request", cmr) + audit.AddEventParameter(auditRec, "command_move_request", cmr.TeamId) defer c.LogAuditRec(auditRec) c.LogAudit("attempt") @@ -148,7 +147,7 @@ func moveCommand(c *Context, w http.ResponseWriter, r *http.Request) { c.Err = appErr return } - auditRec.AddMeta("team", newTeam) + audit.AddEventParameterAuditable(auditRec, "team", newTeam) if !c.App.SessionHasPermissionToTeam(*c.AppContext.Session(), newTeam.Id, model.PermissionManageSlashCommands) { c.LogAudit("fail - inappropriate permissions") @@ -161,7 +160,7 @@ func moveCommand(c *Context, w http.ResponseWriter, r *http.Request) { c.SetCommandNotFoundError() return } - auditRec.AddMeta("command", cmd) + auditRec.AddEventPriorState(cmd) if !c.App.SessionHasPermissionToTeam(*c.AppContext.Session(), cmd.TeamId, model.PermissionManageSlashCommands) { c.LogAudit("fail - inappropriate permissions") @@ -191,7 +190,7 @@ func deleteCommand(c *Context, w http.ResponseWriter, r *http.Request) { } auditRec := c.MakeAuditRecord("deleteCommand", audit.Fail) - auditRec.AddEventParameter("command_id", c.Params.CommandId) + audit.AddEventParameter(auditRec, "command_id", c.Params.CommandId) defer c.LogAuditRec(auditRec) c.LogAudit("attempt") @@ -200,7 +199,7 @@ func deleteCommand(c *Context, w http.ResponseWriter, r *http.Request) { c.SetCommandNotFoundError() return } - auditRec.AddMeta("command", cmd) + auditRec.AddEventPriorState(cmd) if !c.App.SessionHasPermissionToTeam(*c.AppContext.Session(), cmd.TeamId, model.PermissionManageSlashCommands) { c.LogAudit("fail - inappropriate permissions") @@ -222,7 +221,6 @@ func deleteCommand(c *Context, w http.ResponseWriter, r *http.Request) { return } - auditRec.AddEventResultState(cmd) auditRec.AddEventObjectType("command") auditRec.Success() c.LogAudit("success") @@ -323,8 +321,7 @@ func executeCommand(c *Context, w http.ResponseWriter, r *http.Request) { auditRec := c.MakeAuditRecord("executeCommand", audit.Fail) defer c.LogAuditRec(auditRec) - auditRec.AddEventParameter("command_args", commandArgs) - auditRec.AddMeta("commandargs", commandArgs) + audit.AddEventParameterAuditable(auditRec, "command_args", &commandArgs) // checks that user is a member of the specified channel, and that they have permission to use slash commands in it if !c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), commandArgs.ChannelId, model.PermissionUseSlashCommands) { @@ -358,8 +355,6 @@ func executeCommand(c *Context, w http.ResponseWriter, r *http.Request) { commandArgs.SiteURL = c.GetSiteURLHeader() commandArgs.Session = *c.AppContext.Session() - auditRec.AddMeta("commandargs", commandArgs) // overwrite in case teamid changed. TODO do we need to log this too? is the original commandArgs not enough - response, err := c.App.ExecuteCommand(c.AppContext, &commandArgs) if err != nil { c.Err = err @@ -456,12 +451,12 @@ func regenCommandToken(c *Context, w http.ResponseWriter, r *http.Request) { cmd, err := c.App.GetCommand(c.Params.CommandId) if err != nil { - auditRec.AddMeta("command_id", c.Params.CommandId) + audit.AddEventParameter(auditRec, "command_id", c.Params.CommandId) c.SetCommandNotFoundError() return } - auditRec.AddMeta("command", cmd) - auditRec.AddEventParameter("command_id", c.Params.CommandId) + auditRec.AddEventPriorState(cmd) + audit.AddEventParameter(auditRec, "command_id", c.Params.CommandId) if !c.App.SessionHasPermissionToTeam(*c.AppContext.Session(), cmd.TeamId, model.PermissionManageSlashCommands) { c.LogAudit("fail - inappropriate permissions") @@ -482,7 +477,7 @@ func regenCommandToken(c *Context, w http.ResponseWriter, r *http.Request) { c.Err = err return } - + auditRec.AddEventResultState(rcmd) auditRec.Success() c.LogAudit("success") diff --git a/api4/command_local.go b/api4/command_local.go index 216caa7773..f09182c82b 100644 --- a/api4/command_local.go +++ b/api4/command_local.go @@ -30,7 +30,7 @@ func localCreateCommand(c *Context, w http.ResponseWriter, r *http.Request) { } auditRec := c.MakeAuditRecord("localCreateCommand", audit.Fail) - auditRec.AddEventParameter("command", cmd) + audit.AddEventParameterAuditable(auditRec, "command", &cmd) defer c.LogAuditRec(auditRec) c.LogAudit("attempt") diff --git a/api4/compliance.go b/api4/compliance.go index f7987e1b82..8efbe5c735 100644 --- a/api4/compliance.go +++ b/api4/compliance.go @@ -30,7 +30,7 @@ func createComplianceReport(c *Context, w http.ResponseWriter, r *http.Request) } auditRec := c.MakeAuditRecord("createComplianceReport", audit.Fail) - auditRec.AddEventParameter("compliance", job) + audit.AddEventParameterAuditable(auditRec, "compliance", &job) defer c.LogAuditRec(auditRec) if !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PermissionCreateComplianceExportJob) { @@ -94,7 +94,7 @@ func getComplianceReport(c *Context, w http.ResponseWriter, r *http.Request) { return } - auditRec.AddEventParameter("report_id", c.Params.ReportId) + audit.AddEventParameter(auditRec, "report_id", c.Params.ReportId) job, err := c.App.GetComplianceReport(c.Params.ReportId) if err != nil { c.Err = err @@ -118,7 +118,7 @@ func downloadComplianceReport(c *Context, w http.ResponseWriter, r *http.Request auditRec := c.MakeAuditRecord("downloadComplianceReport", audit.Fail) defer c.LogAuditRec(auditRec) - auditRec.AddEventParameter("compliance_id", c.Params.ReportId) + audit.AddEventParameter(auditRec, "compliance_id", c.Params.ReportId) if !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PermissionDownloadComplianceExportResult) { c.SetPermissionError(model.PermissionDownloadComplianceExportResult) diff --git a/api4/config.go b/api4/config.go index 3d842f0319..611f3d71d2 100644 --- a/api4/config.go +++ b/api4/config.go @@ -118,7 +118,7 @@ func updateConfig(c *Context, w http.ResponseWriter, r *http.Request) { auditRec := c.MakeAuditRecord("updateConfig", audit.Fail) - // auditRec.AddEventParameter("config", cfg) // TODO We can do this but do we want to? + // audit.AddEventParameter(auditRec, "config", cfg) // TODO We can do this but do we want to? defer c.LogAuditRec(auditRec) cfg.SetDefaults() diff --git a/api4/data_retention.go b/api4/data_retention.go index 8fdabc9f7c..11a6117162 100644 --- a/api4/data_retention.go +++ b/api4/data_retention.go @@ -122,7 +122,7 @@ func createPolicy(c *Context, w http.ResponseWriter, r *http.Request) { } auditRec := c.MakeAuditRecord("createPolicy", audit.Fail) defer c.LogAuditRec(auditRec) - auditRec.AddEventParameter("policy", policy) + audit.AddEventParameterAuditable(auditRec, "policy", &policy) if !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PermissionSysconsoleWriteComplianceDataRetentionPolicy) { c.SetPermissionError(model.PermissionSysconsoleWriteComplianceDataRetentionPolicy) @@ -158,7 +158,7 @@ func patchPolicy(c *Context, w http.ResponseWriter, r *http.Request) { auditRec := c.MakeAuditRecord("patchPolicy", audit.Fail) defer c.LogAuditRec(auditRec) - auditRec.AddEventParameter("patch", patch) + audit.AddEventParameterAuditable(auditRec, "patch", &patch) if !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PermissionSysconsoleWriteComplianceDataRetentionPolicy) { c.SetPermissionError(model.PermissionSysconsoleWriteComplianceDataRetentionPolicy) @@ -189,7 +189,7 @@ func deletePolicy(c *Context, w http.ResponseWriter, r *http.Request) { auditRec := c.MakeAuditRecord("deletePolicy", audit.Fail) defer c.LogAuditRec(auditRec) - auditRec.AddEventParameter("policy_id", policyId) + audit.AddEventParameter(auditRec, "policy_id", policyId) if !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PermissionSysconsoleWriteComplianceDataRetentionPolicy) { c.SetPermissionError(model.PermissionSysconsoleWriteComplianceDataRetentionPolicy) return @@ -272,8 +272,8 @@ func addTeamsToPolicy(c *Context, w http.ResponseWriter, r *http.Request) { } auditRec := c.MakeAuditRecord("addTeamsToPolicy", audit.Fail) defer c.LogAuditRec(auditRec) - auditRec.AddEventParameter("policy_id", policyId) - auditRec.AddEventParameter("team_ids", teamIDs) + audit.AddEventParameter(auditRec, "policy_id", policyId) + audit.AddEventParameter(auditRec, "team_ids", teamIDs) if !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PermissionSysconsoleWriteComplianceDataRetentionPolicy) { c.SetPermissionError(model.PermissionSysconsoleWriteComplianceDataRetentionPolicy) return @@ -300,8 +300,8 @@ func removeTeamsFromPolicy(c *Context, w http.ResponseWriter, r *http.Request) { } auditRec := c.MakeAuditRecord("removeTeamsFromPolicy", audit.Fail) defer c.LogAuditRec(auditRec) - auditRec.AddEventParameter("policy_id", policyId) - auditRec.AddEventParameter("team_ids", teamIDs) + audit.AddEventParameter(auditRec, "policy_id", policyId) + audit.AddEventParameter(auditRec, "team_ids", teamIDs) if !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PermissionSysconsoleWriteComplianceDataRetentionPolicy) { c.SetPermissionError(model.PermissionSysconsoleWriteComplianceDataRetentionPolicy) @@ -393,8 +393,8 @@ func addChannelsToPolicy(c *Context, w http.ResponseWriter, r *http.Request) { } auditRec := c.MakeAuditRecord("addChannelsToPolicy", audit.Fail) defer c.LogAuditRec(auditRec) - auditRec.AddEventParameter("policy_id", policyId) - auditRec.AddEventParameter("channel_ids", channelIDs) + audit.AddEventParameter(auditRec, "policy_id", policyId) + audit.AddEventParameter(auditRec, "channel_ids", channelIDs) if !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PermissionSysconsoleWriteComplianceDataRetentionPolicy) { c.SetPermissionError(model.PermissionSysconsoleWriteComplianceDataRetentionPolicy) @@ -422,8 +422,8 @@ func removeChannelsFromPolicy(c *Context, w http.ResponseWriter, r *http.Request } auditRec := c.MakeAuditRecord("removeChannelsFromPolicy", audit.Fail) defer c.LogAuditRec(auditRec) - auditRec.AddEventParameter("policy_id", policyId) - auditRec.AddEventParameter("channel_ids", channelIDs) + audit.AddEventParameter(auditRec, "policy_id", policyId) + audit.AddEventParameter(auditRec, "channel_ids", channelIDs) if !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PermissionSysconsoleWriteComplianceDataRetentionPolicy) { c.SetPermissionError(model.PermissionSysconsoleWriteComplianceDataRetentionPolicy) diff --git a/api4/emoji.go b/api4/emoji.go index 9c245d4a8d..b45dbfd2dc 100644 --- a/api4/emoji.go +++ b/api4/emoji.go @@ -136,7 +136,7 @@ func deleteEmoji(c *Context, w http.ResponseWriter, r *http.Request) { emoji, err := c.App.GetEmoji(c.AppContext, c.Params.EmojiId) if err != nil { - auditRec.AddEventParameter("emoji_id", c.Params.EmojiId) + audit.AddEventParameter(auditRec, "emoji_id", c.Params.EmojiId) c.Err = err return } diff --git a/api4/export.go b/api4/export.go index 4abec62fde..08dad1a00f 100644 --- a/api4/export.go +++ b/api4/export.go @@ -43,7 +43,7 @@ func listExports(c *Context, w http.ResponseWriter, r *http.Request) { func deleteExport(c *Context, w http.ResponseWriter, r *http.Request) { auditRec := c.MakeAuditRecord("deleteExport", audit.Fail) defer c.LogAuditRec(auditRec) - auditRec.AddEventParameter("export_name", c.Params.ExportName) + audit.AddEventParameter(auditRec, "export_name", c.Params.ExportName) if !c.IsSystemAdmin() { c.SetPermissionError(model.PermissionManageSystem) diff --git a/api4/file.go b/api4/file.go index 528d7ba442..82fa29668c 100644 --- a/api4/file.go +++ b/api4/file.go @@ -142,7 +142,7 @@ func uploadFileSimple(c *Context, r *http.Request, timestamp time.Time) *model.F auditRec := c.MakeAuditRecord("uploadFileSimple", audit.Fail) defer c.LogAuditRec(auditRec) - auditRec.AddEventParameter("channel_id", c.Params.ChannelId) + audit.AddEventParameter(auditRec, "channel_id", c.Params.ChannelId) if !c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), c.Params.ChannelId, model.PermissionUploadFile) { c.SetPermissionError(model.PermissionUploadFile) @@ -150,7 +150,7 @@ func uploadFileSimple(c *Context, r *http.Request, timestamp time.Time) *model.F } clientId := r.Form.Get("client_id") - auditRec.AddEventParameter("client_id", clientId) + audit.AddEventParameter(auditRec, "client_id", clientId) info, appErr := c.App.UploadFileX(c.AppContext, c.Params.ChannelId, c.Params.Filename, r.Body, app.UploadFileSetTeamId(FileTeamId), @@ -162,7 +162,7 @@ func uploadFileSimple(c *Context, r *http.Request, timestamp time.Time) *model.F c.Err = appErr return nil } - auditRec.AddMeta("file", info) + audit.AddEventParameterAuditable(auditRec, "file", info) fileUploadResponse := &model.FileUploadResponse{ FileInfos: []*model.FileInfo{info}, @@ -312,8 +312,8 @@ NextPart: } auditRec := c.MakeAuditRecord("uploadFileMultipart", audit.Fail) - auditRec.AddEventParameter("channel_id", c.Params.ChannelId) - auditRec.AddEventParameter("client_id", clientId) + audit.AddEventParameter(auditRec, "channel_id", c.Params.ChannelId) + audit.AddEventParameter(auditRec, "client_id", clientId) info, appErr := c.App.UploadFileX(c.AppContext, c.Params.ChannelId, filename, part, app.UploadFileSetTeamId(FileTeamId), @@ -326,7 +326,7 @@ NextPart: c.LogAuditRec(auditRec) return nil } - auditRec.AddMeta("file", info) + audit.AddEventParameterAuditable(auditRec, "file", info) auditRec.Success() c.LogAuditRec(auditRec) @@ -415,8 +415,8 @@ func uploadFileMultipartLegacy(c *Context, mr *multipart.Reader, auditRec := c.MakeAuditRecord("uploadFileMultipartLegacy", audit.Fail) defer c.LogAuditRec(auditRec) - auditRec.AddEventParameter("channel_id", channelId) - auditRec.AddEventParameter("client_id", clientId) + audit.AddEventParameter(auditRec, "channel_id", channelId) + audit.AddEventParameter(auditRec, "client_id", clientId) info, appErr := c.App.UploadFileX(c.AppContext, c.Params.ChannelId, fileHeader.Filename, f, app.UploadFileSetTeamId(FileTeamId), @@ -430,7 +430,7 @@ func uploadFileMultipartLegacy(c *Context, mr *multipart.Reader, c.LogAuditRec(auditRec) return nil } - auditRec.AddMeta("file", info) + audit.AddEventParameterAuditable(auditRec, "file", info) auditRec.Success() c.LogAuditRec(auditRec) @@ -454,7 +454,7 @@ func getFile(c *Context, w http.ResponseWriter, r *http.Request) { auditRec := c.MakeAuditRecord("getFile", audit.Fail) defer c.LogAuditRec(auditRec) - auditRec.AddEventParameter("force_download", forceDownload) + audit.AddEventParameter(auditRec, "force_download", forceDownload) info, err := c.App.GetFileInfo(c.Params.FileId) if err != nil { @@ -462,7 +462,7 @@ func getFile(c *Context, w http.ResponseWriter, r *http.Request) { setInaccessibleFileHeader(w, err) return } - auditRec.AddMeta("file", info) + audit.AddEventParameterAuditable(auditRec, "file", info) if info.CreatorId != c.AppContext.Session().UserId && !c.App.SessionHasPermissionToChannelByPost(*c.AppContext.Session(), info.PostId, model.PermissionReadChannel) { c.SetPermissionError(model.PermissionReadChannel) @@ -537,7 +537,7 @@ func getFileLink(c *Context, w http.ResponseWriter, r *http.Request) { setInaccessibleFileHeader(w, err) return } - auditRec.AddMeta("file", info) + audit.AddEventParameterAuditable(auditRec, "file", info) if info.CreatorId != c.AppContext.Session().UserId && !c.App.SessionHasPermissionToChannelByPost(*c.AppContext.Session(), info.PostId, model.PermissionReadChannel) { c.SetPermissionError(model.PermissionReadChannel) @@ -554,7 +554,6 @@ func getFileLink(c *Context, w http.ResponseWriter, r *http.Request) { resp["link"] = link auditRec.Success() - auditRec.AddMeta("link", link) w.Write([]byte(model.MapToJSON(resp))) } diff --git a/api4/group.go b/api4/group.go index 59b9ad12c1..eae019d7a3 100644 --- a/api4/group.go +++ b/api4/group.go @@ -185,7 +185,7 @@ func createGroup(c *Context, w http.ResponseWriter, r *http.Request) { auditRec := c.MakeAuditRecord("createGroup", audit.Fail) defer c.LogAuditRec(auditRec) - auditRec.AddEventParameter("group", group) + audit.AddEventParameterAuditable(auditRec, "group", group) newGroup, appErr := c.App.CreateGroupWithUserIds(group) if appErr != nil { @@ -253,7 +253,7 @@ func patchGroup(c *Context, w http.ResponseWriter, r *http.Request) { auditRec := c.MakeAuditRecord("patchGroup", audit.Fail) defer c.LogAuditRec(auditRec) - auditRec.AddEventParameter("group", group) + audit.AddEventParameterAuditable(auditRec, "group", group) if groupPatch.AllowReference != nil && *groupPatch.AllowReference { if groupPatch.Name == nil { @@ -344,9 +344,9 @@ func linkGroupSyncable(c *Context, w http.ResponseWriter, r *http.Request) { auditRec := c.MakeAuditRecord("linkGroupSyncable", audit.Fail) defer c.LogAuditRec(auditRec) - auditRec.AddEventParameter("group_id", c.Params.GroupId) - auditRec.AddEventParameter("syncable_id", syncableID) - auditRec.AddEventParameter("syncable_type", syncableType) + audit.AddEventParameter(auditRec, "group_id", c.Params.GroupId) + audit.AddEventParameter(auditRec, "syncable_id", syncableID) + audit.AddEventParameter(auditRec, "syncable_type", string(syncableType)) var patch *model.GroupSyncablePatch err = json.Unmarshal(body, &patch) @@ -355,7 +355,7 @@ func linkGroupSyncable(c *Context, w http.ResponseWriter, r *http.Request) { return } - auditRec.AddEventParameter("patch", patch) + audit.AddEventParameterAuditable(auditRec, "patch", patch) if !*c.App.Channels().License().Features.LDAPGroups { c.Err = model.NewAppError("Api4.createGroupSyncable", "api.ldap_groups.license_error", nil, "", http.StatusForbidden) @@ -519,9 +519,9 @@ func patchGroupSyncable(c *Context, w http.ResponseWriter, r *http.Request) { auditRec := c.MakeAuditRecord("patchGroupSyncable", audit.Fail) defer c.LogAuditRec(auditRec) - auditRec.AddEventParameter("group_id", c.Params.GroupId) - auditRec.AddEventParameter("old_syncable_id", syncableID) - auditRec.AddEventParameter("old_syncable_type", syncableType) + audit.AddEventParameter(auditRec, "group_id", c.Params.GroupId) + audit.AddEventParameter(auditRec, "old_syncable_id", syncableID) + audit.AddEventParameter(auditRec, "old_syncable_type", string(syncableType)) var patch *model.GroupSyncablePatch err = json.Unmarshal(body, &patch) @@ -530,7 +530,7 @@ func patchGroupSyncable(c *Context, w http.ResponseWriter, r *http.Request) { return } - auditRec.AddEventParameter("patch", patch) + audit.AddEventParameterAuditable(auditRec, "patch", patch) if !*c.App.Channels().License().Features.LDAPGroups { c.Err = model.NewAppError("Api4.patchGroupSyncable", "api.ldap_groups.license_error", nil, "", @@ -599,9 +599,9 @@ func unlinkGroupSyncable(c *Context, w http.ResponseWriter, r *http.Request) { auditRec := c.MakeAuditRecord("unlinkGroupSyncable", audit.Fail) defer c.LogAuditRec(auditRec) - auditRec.AddEventParameter("group_id", c.Params.GroupId) - auditRec.AddEventParameter("syncable_id", syncableID) - auditRec.AddEventParameter("syncable_type", syncableType) + audit.AddEventParameter(auditRec, "group_id", c.Params.GroupId) + audit.AddEventParameter(auditRec, "syncable_id", syncableID) + audit.AddEventParameter(auditRec, "syncable_type", string(syncableType)) if !*c.App.Channels().License().Features.LDAPGroups { c.Err = model.NewAppError("Api4.unlinkGroupSyncable", "api.ldap_groups.license_error", nil, "", http.StatusForbidden) @@ -1143,7 +1143,7 @@ func deleteGroup(c *Context, w http.ResponseWriter, r *http.Request) { auditRec := c.MakeAuditRecord("deleteGroup", audit.Fail) defer c.LogAuditRec(auditRec) - auditRec.AddEventParameter("group_id", c.Params.GroupId) + audit.AddEventParameter(auditRec, "group_id", c.Params.GroupId) _, err = c.App.DeleteGroup(c.Params.GroupId) if err != nil { @@ -1192,7 +1192,7 @@ func restoreGroup(c *Context, w http.ResponseWriter, r *http.Request) { auditRec := c.MakeAuditRecord("restoreGroup", audit.Fail) defer c.LogAuditRec(auditRec) - auditRec.AddMeta("group_id", c.Params.GroupId) + audit.AddEventParameter(auditRec, "group_id", c.Params.GroupId) _, err = c.App.RestoreGroup(c.Params.GroupId) if err != nil { @@ -1247,7 +1247,7 @@ func addGroupMembers(c *Context, w http.ResponseWriter, r *http.Request) { auditRec := c.MakeAuditRecord("addGroupMembers", audit.Fail) defer c.LogAuditRec(auditRec) - auditRec.AddEventParameter("addGroupMembers", newMembers) + audit.AddEventParameter(auditRec, "addGroupMembers_userids", newMembers.UserIds) members, appErr := c.App.UpsertGroupMembers(c.Params.GroupId, newMembers.UserIds) if appErr != nil { @@ -1306,7 +1306,7 @@ func deleteGroupMembers(c *Context, w http.ResponseWriter, r *http.Request) { auditRec := c.MakeAuditRecord("deleteGroupMembers", audit.Fail) defer c.LogAuditRec(auditRec) - auditRec.AddEventParameter("deleteGroupMembers", deleteBody) + audit.AddEventParameter(auditRec, "deleteGroupMembers_userids", deleteBody.UserIds) members, appErr := c.App.DeleteGroupMembers(c.Params.GroupId, deleteBody.UserIds) if appErr != nil { diff --git a/api4/job.go b/api4/job.go index a32259cc63..be8f5aadf6 100644 --- a/api4/job.go +++ b/api4/job.go @@ -113,7 +113,7 @@ func createJob(c *Context, w http.ResponseWriter, r *http.Request) { auditRec := c.MakeAuditRecord("createJob", audit.Fail) defer c.LogAuditRec(auditRec) - auditRec.AddEventParameter("job", job) + audit.AddEventParameterAuditable(auditRec, "job", &job) hasPermission, permissionRequired := c.App.SessionHasPermissionToCreateJob(*c.AppContext.Session(), &job) if permissionRequired == nil { @@ -216,7 +216,7 @@ func cancelJob(c *Context, w http.ResponseWriter, r *http.Request) { auditRec := c.MakeAuditRecord("cancelJob", audit.Fail) defer c.LogAuditRec(auditRec) - auditRec.AddEventParameter("job_id", c.Params.JobId) + audit.AddEventParameter(auditRec, "job_id", c.Params.JobId) job, err := c.App.GetJob(c.Params.JobId) if err != nil { diff --git a/api4/ldap.go b/api4/ldap.go index aabacc7599..b5614d29bf 100644 --- a/api4/ldap.go +++ b/api4/ldap.go @@ -156,7 +156,7 @@ func linkLdapGroup(c *Context, w http.ResponseWriter, r *http.Request) { auditRec := c.MakeAuditRecord("linkLdapGroup", audit.Fail) defer c.LogAuditRec(auditRec) - auditRec.AddEventParameter("remote_id", c.Params.RemoteId) + audit.AddEventParameter(auditRec, "remote_id", c.Params.RemoteId) if c.App.Channels().License() == nil || !*c.App.Channels().License().Features.LDAPGroups { c.Err = model.NewAppError("Api4.linkLdapGroup", "api.ldap_groups.license_error", nil, "", http.StatusNotImplemented) @@ -169,8 +169,6 @@ func linkLdapGroup(c *Context, w http.ResponseWriter, r *http.Request) { return } - auditRec.AddMeta("ldap_group", ldapGroup) - if ldapGroup == nil { c.Err = model.NewAppError("Api4.linkLdapGroup", "api.ldap_group.not_found", nil, "", http.StatusNotFound) return @@ -182,7 +180,7 @@ func linkLdapGroup(c *Context, w http.ResponseWriter, r *http.Request) { return } if group != nil { - auditRec.AddMeta("group", group) + audit.AddEventParameterAuditable(auditRec, "group", group) } var status int @@ -253,7 +251,7 @@ func unlinkLdapGroup(c *Context, w http.ResponseWriter, r *http.Request) { auditRec := c.MakeAuditRecord("unlinkLdapGroup", audit.Fail) defer c.LogAuditRec(auditRec) - auditRec.AddEventParameter("remote_id", c.Params.RemoteId) + audit.AddEventParameter(auditRec, "remote_id", c.Params.RemoteId) if !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PermissionSysconsoleWriteUserManagementGroups) { c.SetPermissionError(model.PermissionSysconsoleWriteUserManagementGroups) @@ -295,7 +293,7 @@ func migrateIdLdap(c *Context, w http.ResponseWriter, r *http.Request) { } auditRec := c.MakeAuditRecord("idMigrateLdap", audit.Fail) - auditRec.AddEventParameter("props", props) + audit.AddEventParameter(auditRec, "to_attribute", toAttribute) defer c.LogAuditRec(auditRec) if !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PermissionManageSystem) { @@ -351,7 +349,7 @@ func addLdapPublicCertificate(c *Context, w http.ResponseWriter, r *http.Request auditRec := c.MakeAuditRecord("addLdapPublicCertificate", audit.Fail) defer c.LogAuditRec(auditRec) - auditRec.AddEventParameter("filename", fileData.Filename) + audit.AddEventParameter(auditRec, "filename", fileData.Filename) if err := c.App.AddLdapPublicCertificate(fileData); err != nil { c.Err = err @@ -375,7 +373,7 @@ func addLdapPrivateCertificate(c *Context, w http.ResponseWriter, r *http.Reques auditRec := c.MakeAuditRecord("addLdapPrivateCertificate", audit.Fail) defer c.LogAuditRec(auditRec) - auditRec.AddEventParameter("filename", fileData.Filename) + audit.AddEventParameter(auditRec, "filename", fileData.Filename) if err := c.App.AddLdapPrivateCertificate(fileData); err != nil { c.Err = err diff --git a/api4/license.go b/api4/license.go index c7b81441df..74ae95e56f 100644 --- a/api4/license.go +++ b/api4/license.go @@ -88,7 +88,7 @@ func addLicense(c *Context, w http.ResponseWriter, r *http.Request) { } fileData := fileArray[0] - auditRec.AddEventParameter("filename", fileData.Filename) + audit.AddEventParameter(auditRec, "filename", fileData.Filename) file, err := fileData.Open() if err != nil { diff --git a/api4/license_local.go b/api4/license_local.go index 9634fe0488..d4f88d0b3b 100644 --- a/api4/license_local.go +++ b/api4/license_local.go @@ -44,7 +44,7 @@ func localAddLicense(c *Context, w http.ResponseWriter, r *http.Request) { } fileData := fileArray[0] - auditRec.AddEventParameter("filename", fileData.Filename) + audit.AddEventParameter(auditRec, "filename", fileData.Filename) file, err := fileData.Open() if err != nil { diff --git a/api4/oauth.go b/api4/oauth.go index aa0e72bbfb..f0efd43f63 100644 --- a/api4/oauth.go +++ b/api4/oauth.go @@ -32,7 +32,7 @@ func createOAuthApp(c *Context, w http.ResponseWriter, r *http.Request) { } auditRec := c.MakeAuditRecord("createOAuthApp", audit.Fail) - auditRec.AddEventParameter("oauth_app", oauthApp) + audit.AddEventParameterAuditable(auditRec, "oauth_app", &oauthApp) defer c.LogAuditRec(auditRec) @@ -72,7 +72,7 @@ func updateOAuthApp(c *Context, w http.ResponseWriter, r *http.Request) { auditRec := c.MakeAuditRecord("updateOAuthApp", audit.Fail) defer c.LogAuditRec(auditRec) - auditRec.AddEventParameter("oauth_app_id", c.Params.AppId) + audit.AddEventParameter(auditRec, "oauth_app_id", c.Params.AppId) c.LogAudit("attempt") if !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PermissionManageOAuth) { @@ -85,7 +85,7 @@ func updateOAuthApp(c *Context, w http.ResponseWriter, r *http.Request) { c.SetInvalidParamWithErr("oauth_app", jsonErr) return } - auditRec.AddEventParameter("oauth_app", oauthApp) + audit.AddEventParameterAuditable(auditRec, "oauth_app", &oauthApp) // The app being updated in the payload must be the same one as indicated in the URL. if oauthApp.Id != c.Params.AppId { @@ -209,7 +209,7 @@ func deleteOAuthApp(c *Context, w http.ResponseWriter, r *http.Request) { auditRec := c.MakeAuditRecord("deleteOAuthApp", audit.Fail) defer c.LogAuditRec(auditRec) - auditRec.AddEventParameter("oauth_app_id", c.Params.AppId) + audit.AddEventParameter(auditRec, "oauth_app_id", c.Params.AppId) c.LogAudit("attempt") if !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PermissionManageOAuth) { @@ -250,7 +250,7 @@ func regenerateOAuthAppSecret(c *Context, w http.ResponseWriter, r *http.Request auditRec := c.MakeAuditRecord("regenerateOAuthAppSecret", audit.Fail) defer c.LogAuditRec(auditRec) - auditRec.AddEventParameter("oauth_app_id", c.Params.AppId) + audit.AddEventParameter(auditRec, "oauth_app_id", c.Params.AppId) if !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PermissionManageOAuth) { c.SetPermissionError(model.PermissionManageOAuth) diff --git a/api4/plugin.go b/api4/plugin.go index 4904c88b6d..024f9f00e0 100644 --- a/api4/plugin.go +++ b/api4/plugin.go @@ -73,7 +73,7 @@ func uploadPlugin(c *Context, w http.ResponseWriter, r *http.Request) { c.Err = model.NewAppError("uploadPlugin", "api.plugin.upload.array.app_error", nil, "", http.StatusBadRequest) return } - auditRec.AddEventParameter("filename", pluginArray[0].Filename) + audit.AddEventParameter(auditRec, "filename", pluginArray[0].Filename) file, err := pluginArray[0].Open() if err != nil { @@ -109,7 +109,7 @@ func installPluginFromURL(c *Context, w http.ResponseWriter, r *http.Request) { force, _ := strconv.ParseBool(r.URL.Query().Get("force")) downloadURL := r.URL.Query().Get("plugin_download_url") - auditRec.AddEventParameter("url", downloadURL) + audit.AddEventParameter(auditRec, "url", downloadURL) pluginFileBytes, err := c.App.DownloadFromURL(downloadURL) if err != nil { @@ -145,7 +145,7 @@ func installMarketplacePlugin(c *Context, w http.ResponseWriter, r *http.Request c.Err = model.NewAppError("installMarketplacePlugin", "app.plugin.marketplace_plugin_request.app_error", nil, err.Error(), http.StatusNotImplemented) return } - auditRec.AddEventParameter("plugin_id", pluginRequest.Id) + audit.AddEventParameter(auditRec, "plugin_id", pluginRequest.Id) // Always install the latest compatible version // https://mattermost.atlassian.net/browse/MM-41981 @@ -224,7 +224,7 @@ func removePlugin(c *Context, w http.ResponseWriter, r *http.Request) { auditRec := c.MakeAuditRecord("removePlugin", audit.Fail) defer c.LogAuditRec(auditRec) - auditRec.AddEventParameter("plugin_id", c.Params.PluginId) + audit.AddEventParameter(auditRec, "plugin_id", c.Params.PluginId) if !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PermissionSysconsoleWritePlugins) { c.SetPermissionError(model.PermissionSysconsoleWritePlugins) @@ -324,7 +324,7 @@ func enablePlugin(c *Context, w http.ResponseWriter, r *http.Request) { auditRec := c.MakeAuditRecord("enablePlugin", audit.Fail) defer c.LogAuditRec(auditRec) - auditRec.AddEventParameter("plugin_id", c.Params.PluginId) + audit.AddEventParameter(auditRec, "plugin_id", c.Params.PluginId) if !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PermissionSysconsoleWritePlugins) { c.SetPermissionError(model.PermissionSysconsoleWritePlugins) @@ -353,7 +353,7 @@ func disablePlugin(c *Context, w http.ResponseWriter, r *http.Request) { auditRec := c.MakeAuditRecord("disablePlugin", audit.Fail) defer c.LogAuditRec(auditRec) - auditRec.AddEventParameter("plugin_id", c.Params.PluginId) + audit.AddEventParameter(auditRec, "plugin_id", c.Params.PluginId) if !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PermissionSysconsoleWritePlugins) { c.SetPermissionError(model.PermissionSysconsoleWritePlugins) diff --git a/api4/post.go b/api4/post.go index 2ce216c099..16fa1465ae 100644 --- a/api4/post.go +++ b/api4/post.go @@ -59,7 +59,7 @@ func createPost(c *Context, w http.ResponseWriter, r *http.Request) { auditRec := c.MakeAuditRecord("createPost", audit.Fail) defer c.LogAuditRecWithLevel(auditRec, app.LevelContent) - auditRec.AddEventParameter("post", &post) + audit.AddEventParameterAuditable(auditRec, "post", &post) hasPermission := false if c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), post.ChannelId, model.PermissionCreatePost) { @@ -537,7 +537,7 @@ func deletePost(c *Context, w http.ResponseWriter, _ *http.Request) { auditRec := c.MakeAuditRecord("deletePost", audit.Fail) defer c.LogAuditRecWithLevel(auditRec, app.LevelContent) - auditRec.AddEventParameter("post_id", c.Params.PostId) + audit.AddEventParameter(auditRec, "post_id", c.Params.PostId) post, err := c.App.GetSinglePost(c.Params.PostId, false) if err != nil { @@ -775,7 +775,7 @@ func updatePost(c *Context, w http.ResponseWriter, r *http.Request) { } auditRec := c.MakeAuditRecord("updatePost", audit.Fail) - auditRec.AddEventParameter("post", post.Auditable()) + audit.AddEventParameterAuditable(auditRec, "post", &post) defer c.LogAuditRecWithLevel(auditRec, app.LevelContent) // The post being updated in the payload must be the same one as indicated in the URL. @@ -841,8 +841,8 @@ func patchPost(c *Context, w http.ResponseWriter, r *http.Request) { } auditRec := c.MakeAuditRecord("patchPost", audit.Fail) - auditRec.AddEventParameter("id", c.Params.PostId) - auditRec.AddEventParameter("patch", post.Auditable()) + audit.AddEventParameter(auditRec, "id", c.Params.PostId) + audit.AddEventParameterAuditable(auditRec, "patch", &post) defer c.LogAuditRecWithLevel(auditRec, app.LevelContent) // Updating the file_ids of a post is not a supported operation and will be ignored @@ -952,7 +952,7 @@ func saveIsPinnedPost(c *Context, w http.ResponseWriter, isPinned bool) { } auditRec := c.MakeAuditRecord("saveIsPinnedPost", audit.Fail) - auditRec.AddEventParameter("post_id", c.Params.PostId) + audit.AddEventParameter(auditRec, "post_id", c.Params.PostId) defer c.LogAuditRecWithLevel(auditRec, app.LevelContent) if !c.App.SessionHasPermissionToChannelByPost(*c.AppContext.Session(), c.Params.PostId, model.PermissionReadChannel) { diff --git a/api4/remote_cluster.go b/api4/remote_cluster.go index c70d767cd3..7804a29eb2 100644 --- a/api4/remote_cluster.go +++ b/api4/remote_cluster.go @@ -92,7 +92,7 @@ func remoteClusterAcceptMessage(c *Context, w http.ResponseWriter, r *http.Reque } auditRec := c.MakeAuditRecord("remoteClusterAcceptMessage", audit.Fail) - auditRec.AddEventParameter("remote_cluster_frame", frame) + audit.AddEventParameterAuditable(auditRec, "remote_cluster_frame", &frame) defer c.LogAuditRec(auditRec) remoteId := c.GetRemoteID(r) @@ -106,7 +106,7 @@ func remoteClusterAcceptMessage(c *Context, w http.ResponseWriter, r *http.Reque c.SetInvalidRemoteIdError(frame.RemoteId) return } - auditRec.AddMeta("remoteCluster", rc) + audit.AddEventParameterAuditable(auditRec, "remote_cluster", rc) // pass message to Remote Cluster Service and write response resp := service.ReceiveIncomingMsg(rc, frame.Msg) @@ -139,7 +139,7 @@ func remoteClusterConfirmInvite(c *Context, w http.ResponseWriter, r *http.Reque } auditRec := c.MakeAuditRecord("remoteClusterAcceptInvite", audit.Fail) - auditRec.AddEventParameter("remote_cluster_frame", frame) + audit.AddEventParameterAuditable(auditRec, "remote_cluster_frame", &frame) defer c.LogAuditRec(auditRec) remoteId := c.GetRemoteID(r) @@ -153,7 +153,7 @@ func remoteClusterConfirmInvite(c *Context, w http.ResponseWriter, r *http.Reque c.SetInvalidRemoteIdError(frame.RemoteId) return } - auditRec.AddMeta("remoteCluster", rc) + audit.AddEventParameterAuditable(auditRec, "remote_cluster", rc) if time.Since(model.GetTimeForMillis(rc.CreateAt)) > remotecluster.InviteExpiresAfter { c.Err = model.NewAppError("remoteClusterAcceptMessage", "api.context.invitation_expired.error", nil, "", http.StatusBadRequest) @@ -193,7 +193,7 @@ func uploadRemoteData(c *Context, w http.ResponseWriter, r *http.Request) { auditRec := c.MakeAuditRecord("uploadRemoteData", audit.Fail) defer c.LogAuditRec(auditRec) - auditRec.AddEventParameter("upload_id", c.Params.UploadId) + audit.AddEventParameter(auditRec, "upload_id", c.Params.UploadId) c.AppContext.SetContext(app.WithMaster(c.AppContext.Context())) us, err := c.App.GetUploadSession(c.AppContext, c.Params.UploadId) @@ -264,7 +264,7 @@ func remoteSetProfileImage(c *Context, w http.ResponseWriter, r *http.Request) { auditRec := c.MakeAuditRecord("remoteUploadProfileImage", audit.Fail) defer c.LogAuditRec(auditRec) if imageArray[0] != nil { - auditRec.AddEventParameter("filename", imageArray[0].Filename) + audit.AddEventParameter(auditRec, "filename", imageArray[0].Filename) } user, err := c.App.GetUser(c.Params.UserId) @@ -272,7 +272,7 @@ func remoteSetProfileImage(c *Context, w http.ResponseWriter, r *http.Request) { c.SetInvalidURLParam("user_id") return } - auditRec.AddMeta("user", user) + audit.AddEventParameterAuditable(auditRec, "user", user) imageData := imageArray[0] if err := c.App.SetProfileImage(c.AppContext, c.Params.UserId, imageData); err != nil { diff --git a/api4/role.go b/api4/role.go index e404235ba1..becff7a4e2 100644 --- a/api4/role.go +++ b/api4/role.go @@ -123,7 +123,7 @@ func patchRole(c *Context, w http.ResponseWriter, r *http.Request) { } auditRec := c.MakeAuditRecord("patchRole", audit.Fail) - auditRec.AddEventParameter("role_patch", patch) + audit.AddEventParameterAuditable(auditRec, "role_patch", &patch) defer c.LogAuditRec(auditRec) oldRole, appErr := c.App.GetRole(c.Params.RoleId) diff --git a/api4/saml.go b/api4/saml.go index 893e34f797..6bd027f75c 100644 --- a/api4/saml.go +++ b/api4/saml.go @@ -83,7 +83,7 @@ func addSamlPublicCertificate(c *Context, w http.ResponseWriter, r *http.Request auditRec := c.MakeAuditRecord("addSamlPublicCertificate", audit.Fail) defer c.LogAuditRec(auditRec) - auditRec.AddEventParameter("filename", fileData.Filename) + audit.AddEventParameter(auditRec, "filename", fileData.Filename) if err := c.App.AddSamlPublicCertificate(fileData); err != nil { c.Err = err @@ -107,7 +107,7 @@ func addSamlPrivateCertificate(c *Context, w http.ResponseWriter, r *http.Reques auditRec := c.MakeAuditRecord("addSamlPrivateCertificate", audit.Fail) defer c.LogAuditRec(auditRec) - auditRec.AddEventParameter("filename", fileData.Filename) + audit.AddEventParameter(auditRec, "filename", fileData.Filename) if err := c.App.AddSamlPrivateCertificate(fileData); err != nil { c.Err = err @@ -155,7 +155,7 @@ func addSamlIdpCertificate(c *Context, w http.ResponseWriter, r *http.Request) { c.Err = err return } - auditRec.AddEventParameter("filename", fileData.Filename) + audit.AddEventParameter(auditRec, "filename", fileData.Filename) if err := c.App.AddSamlIdpCertificate(fileData); err != nil { c.Err = err diff --git a/api4/scheme.go b/api4/scheme.go index 82421ee610..91de5c1ddb 100644 --- a/api4/scheme.go +++ b/api4/scheme.go @@ -31,7 +31,7 @@ func createScheme(c *Context, w http.ResponseWriter, r *http.Request) { auditRec := c.MakeAuditRecord("createScheme", audit.Fail) defer c.LogAuditRec(auditRec) - auditRec.AddEventParameter("scheme", scheme) + audit.AddEventParameterAuditable(auditRec, "scheme", &scheme) if c.App.Channels().License() == nil || (!*c.App.Channels().License().Features.CustomPermissionsSchemes && c.App.Channels().License().SkuShortName != model.LicenseShortSkuProfessional) { c.Err = model.NewAppError("Api4.CreateScheme", "api.scheme.create_scheme.license.error", nil, "", http.StatusNotImplemented) @@ -191,7 +191,7 @@ func patchScheme(c *Context, w http.ResponseWriter, r *http.Request) { } auditRec := c.MakeAuditRecord("patchScheme", audit.Fail) - auditRec.AddEventParameter("scheme_patch", patch) + audit.AddEventParameterAuditable(auditRec, "scheme_patch", &patch) defer c.LogAuditRec(auditRec) if c.App.Channels().License() == nil || (!*c.App.Channels().License().Features.CustomPermissionsSchemes && c.App.Channels().License().SkuShortName != model.LicenseShortSkuProfessional) { @@ -199,7 +199,7 @@ func patchScheme(c *Context, w http.ResponseWriter, r *http.Request) { return } - auditRec.AddEventParameter("scheme_id", c.Params.SchemeId) + audit.AddEventParameter(auditRec, "scheme_id", c.Params.SchemeId) scheme, err := c.App.GetScheme(c.Params.SchemeId) if err != nil { @@ -236,7 +236,7 @@ func deleteScheme(c *Context, w http.ResponseWriter, r *http.Request) { } auditRec := c.MakeAuditRecord("deleteScheme", audit.Fail) - auditRec.AddEventParameter("scheme_id", c.Params.SchemeId) + audit.AddEventParameter(auditRec, "scheme_id", c.Params.SchemeId) defer c.LogAuditRec(auditRec) if c.App.Channels().License() == nil || (!*c.App.Channels().License().Features.CustomPermissionsSchemes && c.App.Channels().License().SkuShortName != model.LicenseShortSkuProfessional) { diff --git a/api4/system.go b/api4/system.go index 5220e66e60..bf2b244b36 100644 --- a/api4/system.go +++ b/api4/system.go @@ -273,8 +273,8 @@ func getAudits(c *Context, w http.ResponseWriter, r *http.Request) { } auditRec.Success() - auditRec.AddEventParameter("page", c.Params.Page) - auditRec.AddEventParameter("audits_per_page", c.Params.LogsPerPage) + audit.AddEventParameter(auditRec, "page", c.Params.Page) + audit.AddEventParameter(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)) @@ -393,8 +393,8 @@ func getLogs(c *Context, w http.ResponseWriter, r *http.Request) { return } - auditRec.AddEventParameter("page", c.Params.Page) - auditRec.AddEventParameter("logs_per_page", c.Params.LogsPerPage) + audit.AddEventParameter(auditRec, "page", c.Params.Page) + audit.AddEventParameter(auditRec, "logs_per_page", c.Params.LogsPerPage) w.Write([]byte(model.ArrayToJSON(lines))) } @@ -686,7 +686,7 @@ func setServerBusy(c *Context, w http.ResponseWriter, r *http.Request) { auditRec := c.MakeAuditRecord("setServerBusy", audit.Fail) defer c.LogAuditRec(auditRec) - auditRec.AddEventParameter("seconds", i) + audit.AddEventParameter(auditRec, "seconds", i) c.App.Srv().Platform().Busy.Set(time.Second * time.Duration(i)) mlog.Warn("server busy state activated - non-critical services disabled", mlog.Int64("seconds", i)) @@ -1001,8 +1001,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 } - auditRec.AddEventParameter("install_plugin", onboardingRequest.InstallPlugins) - auditRec.AddEventParameter("onboarding_request", onboardingRequest) + audit.AddEventParameter(auditRec, "install_plugin", onboardingRequest.InstallPlugins) + audit.AddEventParameterAuditable(auditRec, "onboarding_request", onboardingRequest) appErr := c.App.CompleteOnboarding(c.AppContext, onboardingRequest) if appErr != nil { diff --git a/api4/team.go b/api4/team.go index 49aa1d372e..0f0fe97651 100644 --- a/api4/team.go +++ b/api4/team.go @@ -87,7 +87,7 @@ func createTeam(c *Context, w http.ResponseWriter, r *http.Request) { auditRec := c.MakeAuditRecord("createTeam", audit.Fail) defer c.LogAuditRec(auditRec) - auditRec.AddEventParameter("team", team) + audit.AddEventParameterAuditable(auditRec, "team", &team) if !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PermissionCreateTeam) { c.Err = model.NewAppError("createTeam", "api.team.is_team_creation_allowed.disabled.app_error", nil, "", http.StatusForbidden) @@ -203,7 +203,7 @@ func updateTeam(c *Context, w http.ResponseWriter, r *http.Request) { auditRec := c.MakeAuditRecord("updateTeam", audit.Fail) defer c.LogAuditRec(auditRec) - auditRec.AddEventParameter("team", team) + audit.AddEventParameterAuditable(auditRec, "team", &team) if !c.App.SessionHasPermissionToTeam(*c.AppContext.Session(), c.Params.TeamId, model.PermissionManageTeam) { c.SetPermissionError(model.PermissionManageTeam) @@ -239,7 +239,7 @@ func patchTeam(c *Context, w http.ResponseWriter, r *http.Request) { } auditRec := c.MakeAuditRecord("patchTeam", audit.Fail) - auditRec.AddEventParameter("team_patch", team) + audit.AddEventParameterAuditable(auditRec, "team_patch", &team) defer c.LogAuditRec(auditRec) if !c.App.SessionHasPermissionToTeam(*c.AppContext.Session(), c.Params.TeamId, model.PermissionManageTeam) { @@ -278,7 +278,7 @@ func restoreTeam(c *Context, w http.ResponseWriter, r *http.Request) { auditRec := c.MakeAuditRecord("restoreTeam", audit.Fail) defer c.LogAuditRec(auditRec) - auditRec.AddEventParameter("team_id", c.Params.TeamId) + audit.AddEventParameter(auditRec, "team_id", c.Params.TeamId) if !c.App.SessionHasPermissionToTeam(*c.AppContext.Session(), c.Params.TeamId, model.PermissionManageTeam) { c.SetPermissionError(model.PermissionManageTeam) @@ -354,11 +354,11 @@ func updateTeamPrivacy(c *Context, w http.ResponseWriter, r *http.Request) { } auditRec := c.MakeAuditRecord("updateTeamPrivacy", audit.Fail) - auditRec.AddEventParameter("props", props) + audit.AddEventParameter(auditRec, "privacy", privacy) defer c.LogAuditRec(auditRec) if !c.App.SessionHasPermissionToTeam(*c.AppContext.Session(), c.Params.TeamId, model.PermissionManageTeam) { - auditRec.AddEventParameter("team_id", c.Params.TeamId) + audit.AddEventParameter(auditRec, "team_id", c.Params.TeamId) c.SetPermissionError(model.PermissionManageTeam) return } @@ -396,7 +396,7 @@ func regenerateTeamInviteId(c *Context, w http.ResponseWriter, r *http.Request) } auditRec := c.MakeAuditRecord("regenerateTeamInviteId", audit.Fail) - auditRec.AddEventParameter("team_id", c.Params.TeamId) + audit.AddEventParameter(auditRec, "team_id", c.Params.TeamId) defer c.LogAuditRec(auditRec) patchedTeam, err := c.App.RegenerateTeamInviteId(c.Params.TeamId) @@ -436,7 +436,7 @@ func deleteTeam(c *Context, w http.ResponseWriter, r *http.Request) { defer c.LogAuditRec(auditRec) if team, err := c.App.GetTeam(c.Params.TeamId); err == nil { - auditRec.AddEventParameter("team", team) + audit.AddEventParameterAuditable(auditRec, "team", team) } var err *model.AppError @@ -715,7 +715,7 @@ func addTeamMember(c *Context, w http.ResponseWriter, r *http.Request) { } auditRec := c.MakeAuditRecord("addTeamMember", audit.Fail) - auditRec.AddEventParameter("member", member) + audit.AddEventParameterAuditable(auditRec, "member", &member) defer c.LogAuditRec(auditRec) if member.UserId == c.AppContext.Session().UserId { @@ -746,7 +746,7 @@ func addTeamMember(c *Context, w http.ResponseWriter, r *http.Request) { c.Err = err return } - auditRec.AddMeta("team", team) + audit.AddEventParameterAuditable(auditRec, "team", team) if team.IsGroupConstrained() { nonMembers, err := c.App.FilterNonGroupTeamMembers([]string{member.UserId}, team) @@ -790,7 +790,7 @@ func addUserToTeamFromInvite(c *Context, w http.ResponseWriter, r *http.Request) auditRec := c.MakeAuditRecord("addUserToTeamFromInvite", audit.Fail) defer c.LogAuditRec(auditRec) - auditRec.AddEventParameter("invite_id", inviteId) + audit.AddEventParameter(auditRec, "invite_id", inviteId) if tokenId != "" { member, err = c.App.AddTeamMemberByToken(c.AppContext, c.AppContext.Session().UserId, tokenId) @@ -847,7 +847,7 @@ func addTeamMembers(c *Context, w http.ResponseWriter, r *http.Request) { } auditRec := c.MakeAuditRecord("addTeamMembers", audit.Fail) - auditRec.AddEventParameter("members", members) + audit.AddEventParameterAuditableArray(auditRec, "members", members) defer c.LogAuditRec(auditRec) auditRec.AddMeta("count", len(members)) @@ -862,7 +862,7 @@ func addTeamMembers(c *Context, w http.ResponseWriter, r *http.Request) { c.Err = appErr return } - auditRec.AddMeta("team", team) + audit.AddEventParameterAuditable(auditRec, "team", team) if team.IsGroupConstrained() { nonMembers, err := c.App.FilterNonGroupTeamMembers(memberIDs, team) @@ -953,22 +953,22 @@ func removeTeamMember(c *Context, w http.ResponseWriter, r *http.Request) { } } - auditRec.AddEventParameter("team_id", c.Params.TeamId) - auditRec.AddEventParameter("user_id", c.Params.UserId) + audit.AddEventParameter(auditRec, "team_id", c.Params.TeamId) + audit.AddEventParameter(auditRec, "user_id", c.Params.UserId) team, err := c.App.GetTeam(c.Params.TeamId) if err != nil { c.Err = err return } - auditRec.AddMeta("team", team) + audit.AddEventParameterAuditable(auditRec, "team", team) user, err := c.App.GetUser(c.Params.UserId) if err != nil { c.Err = err return } - auditRec.AddMeta("user", user) + audit.AddEventParameterAuditable(auditRec, "user", user) if team.IsGroupConstrained() && (c.Params.UserId != c.AppContext.Session().UserId) && !user.IsBot { c.Err = model.NewAppError("removeTeamMember", "api.team.remove_member.group_constrained.app_error", nil, "", http.StatusBadRequest) @@ -1055,7 +1055,7 @@ func updateTeamMemberRoles(c *Context, w http.ResponseWriter, r *http.Request) { auditRec := c.MakeAuditRecord("updateTeamMemberRoles", audit.Fail) defer c.LogAuditRec(auditRec) - auditRec.AddEventParameter("props", props) + audit.AddEventParameter(auditRec, "roles", newRoles) if !c.App.SessionHasPermissionToTeam(*c.AppContext.Session(), c.Params.TeamId, model.PermissionManageTeamRoles) { c.SetPermissionError(model.PermissionManageTeamRoles) @@ -1089,7 +1089,7 @@ func updateTeamMemberSchemeRoles(c *Context, w http.ResponseWriter, r *http.Requ auditRec := c.MakeAuditRecord("updateTeamMemberSchemeRoles", audit.Fail) defer c.LogAuditRec(auditRec) - auditRec.AddEventParameter("scheme_roles", schemeRoles) + audit.AddEventParameterAuditable(auditRec, "scheme_roles", &schemeRoles) if !c.App.SessionHasPermissionToTeam(*c.AppContext.Session(), c.Params.TeamId, model.PermissionManageTeamRoles) { c.SetPermissionError(model.PermissionManageTeamRoles) @@ -1321,7 +1321,7 @@ func importTeam(c *Context, w http.ResponseWriter, r *http.Request) { auditRec := c.MakeAuditRecord("importTeam", audit.Fail) defer c.LogAuditRec(auditRec) - auditRec.AddEventParameter("team_id", c.Params.TeamId) + audit.AddEventParameter(auditRec, "team_id", c.Params.TeamId) fileInfo := fileInfoArray[0] @@ -1331,9 +1331,9 @@ func importTeam(c *Context, w http.ResponseWriter, r *http.Request) { return } defer fileData.Close() - auditRec.AddEventParameter("filename", fileInfo.Filename) - auditRec.AddEventParameter("filesize", fileSize) - auditRec.AddEventParameter("from", importFrom) + audit.AddEventParameter(auditRec, "filename", fileInfo.Filename) + audit.AddEventParameter(auditRec, "filesize", fileSize) + audit.AddEventParameter(auditRec, "from", importFrom) var log *bytes.Buffer data := map[string]string{} @@ -1399,8 +1399,8 @@ func inviteUsersToTeam(c *Context, w http.ResponseWriter, r *http.Request) { auditRec := c.MakeAuditRecord("inviteUsersToTeam", audit.Fail) defer c.LogAuditRec(auditRec) - auditRec.AddEventParameter("member_invite", memberInvite) - auditRec.AddEventParameter("team_id", c.Params.TeamId) + audit.AddEventParameterAuditable(auditRec, "member_invite", memberInvite) + audit.AddEventParameter(auditRec, "team_id", c.Params.TeamId) auditRec.AddMeta("count", len(emailList)) auditRec.AddMeta("emails", emailList) @@ -1491,7 +1491,7 @@ func inviteGuestsToChannels(c *Context, w http.ResponseWriter, r *http.Request) auditRec := c.MakeAuditRecord("inviteGuestsToChannels", audit.Fail) defer c.LogAuditRec(auditRec) - auditRec.AddEventParameter("team_id", c.Params.TeamId) + audit.AddEventParameter(auditRec, "team_id", c.Params.TeamId) if !c.App.SessionHasPermissionToTeam(*c.AppContext.Session(), c.Params.TeamId, model.PermissionInviteGuest) { c.SetPermissionError(model.PermissionInviteGuest) @@ -1510,7 +1510,7 @@ func inviteGuestsToChannels(c *Context, w http.ResponseWriter, r *http.Request) c.Err = model.NewAppError("Api4.inviteGuestsToChannels", "api.team.invite_guests_to_channels.invalid_body.app_error", nil, "", http.StatusBadRequest).Wrap(err) return } - auditRec.AddEventParameter("guests_invite", guestsInvite) + audit.AddEventParameterAuditable(auditRec, "guests_invite", &guestsInvite) for i, email := range guestsInvite.Emails { guestsInvite.Emails[i] = strings.ToLower(email) @@ -1663,7 +1663,7 @@ func setTeamIcon(c *Context, w http.ResponseWriter, r *http.Request) { auditRec := c.MakeAuditRecord("setTeamIcon", audit.Fail) defer c.LogAuditRec(auditRec) - auditRec.AddEventParameter("team_id", c.Params.TeamId) + audit.AddEventParameter(auditRec, "team_id", c.Params.TeamId) if !c.App.SessionHasPermissionToTeam(*c.AppContext.Session(), c.Params.TeamId, model.PermissionManageTeam) { c.SetPermissionError(model.PermissionManageTeam) @@ -1714,7 +1714,7 @@ func removeTeamIcon(c *Context, w http.ResponseWriter, r *http.Request) { auditRec := c.MakeAuditRecord("removeTeamIcon", audit.Fail) defer c.LogAuditRec(auditRec) - auditRec.AddEventParameter("team_id", c.Params.TeamId) + audit.AddEventParameter(auditRec, "team_id", c.Params.TeamId) if !c.App.SessionHasPermissionToTeam(*c.AppContext.Session(), c.Params.TeamId, model.PermissionManageTeam) { c.SetPermissionError(model.PermissionManageTeam) @@ -1751,7 +1751,7 @@ func updateTeamScheme(c *Context, w http.ResponseWriter, r *http.Request) { } auditRec := c.MakeAuditRecord("updateTeamScheme", audit.Fail) - auditRec.AddEventParameter("scheme_id_patch", p) + audit.AddEventParameterAuditable(auditRec, "scheme_id_patch", &p) defer c.LogAuditRec(auditRec) if c.App.Channels().License() == nil { @@ -1770,7 +1770,7 @@ func updateTeamScheme(c *Context, w http.ResponseWriter, r *http.Request) { c.Err = err return } - auditRec.AddMeta("scheme", scheme) + audit.AddEventParameterAuditable(auditRec, "scheme", scheme) if scheme.Scope != model.SchemeScopeTeam { c.Err = model.NewAppError("Api4.UpdateTeamScheme", "api.team.update_team_scheme.scheme_scope.error", nil, "", http.StatusBadRequest) @@ -1783,7 +1783,7 @@ func updateTeamScheme(c *Context, w http.ResponseWriter, r *http.Request) { c.Err = err return } - auditRec.AddMeta("team", team) + audit.AddEventParameterAuditable(auditRec, "team", team) team.SchemeId = schemeID diff --git a/api4/team_local.go b/api4/team_local.go index ff9b4da4b3..a1e227a64d 100644 --- a/api4/team_local.go +++ b/api4/team_local.go @@ -44,7 +44,7 @@ func localDeleteTeam(c *Context, w http.ResponseWriter, r *http.Request) { } auditRec := c.MakeAuditRecord("localDeleteTeam", audit.Fail) - auditRec.AddEventParameter("team_id", c.Params.TeamId) + audit.AddEventParameter(auditRec, "team_id", c.Params.TeamId) defer c.LogAuditRec(auditRec) if team, err := c.App.GetTeam(c.Params.TeamId); err == nil { @@ -107,9 +107,9 @@ func localInviteUsersToTeam(c *Context, w http.ResponseWriter, r *http.Request) } auditRec := c.MakeAuditRecord("localInviteUsersToTeam", audit.Fail) - auditRec.AddEventParameter("member_invite", memberInvite) + audit.AddEventParameterAuditable(auditRec, "member_invite", memberInvite) defer c.LogAuditRec(auditRec) - auditRec.AddEventParameter("team_id", c.Params.TeamId) + audit.AddEventParameter(auditRec, "team_id", c.Params.TeamId) auditRec.AddMeta("count", len(emailList)) auditRec.AddMeta("emails", emailList) @@ -254,7 +254,7 @@ func localCreateTeam(c *Context, w http.ResponseWriter, r *http.Request) { auditRec := c.MakeAuditRecord("localCreateTeam", audit.Fail) defer c.LogAuditRec(auditRec) - auditRec.AddEventParameter("team", team) + audit.AddEventParameterAuditable(auditRec, "team", &team) rteam, err := c.App.CreateTeam(c.AppContext, &team) if err != nil { @@ -266,7 +266,6 @@ func localCreateTeam(c *Context, w http.ResponseWriter, r *http.Request) { auditRec.AddEventResultState(rteam) auditRec.AddEventObjectType("type") auditRec.Success() - auditRec.AddMeta("team", team) // overwrite meta w.WriteHeader(http.StatusCreated) if err := json.NewEncoder(w).Encode(rteam); err != nil { diff --git a/api4/upload.go b/api4/upload.go index 37f5a1bb01..94f34231e8 100644 --- a/api4/upload.go +++ b/api4/upload.go @@ -42,7 +42,7 @@ func createUpload(c *Context, w http.ResponseWriter, r *http.Request) { auditRec := c.MakeAuditRecord("createUpload", audit.Fail) defer c.LogAuditRec(auditRec) - auditRec.AddEventParameter("upload", us) + audit.AddEventParameterAuditable(auditRec, "upload", &us) if us.Type == model.UploadTypeImport { if !c.IsSystemAdmin() { @@ -122,7 +122,7 @@ func uploadData(c *Context, w http.ResponseWriter, r *http.Request) { auditRec := c.MakeAuditRecord("uploadData", audit.Fail) defer c.LogAuditRec(auditRec) - auditRec.AddEventParameter("upload_id", c.Params.UploadId) + audit.AddEventParameter(auditRec, "upload_id", c.Params.UploadId) c.AppContext.SetContext(app.WithMaster(c.AppContext.Context())) us, err := c.App.GetUploadSession(c.AppContext, c.Params.UploadId) diff --git a/api4/user.go b/api4/user.go index 0d09f8f7eb..d70d748257 100644 --- a/api4/user.go +++ b/api4/user.go @@ -123,9 +123,9 @@ func createUser(c *Context, w http.ResponseWriter, r *http.Request) { auditRec := c.MakeAuditRecord("createUser", audit.Fail) defer c.LogAuditRec(auditRec) - auditRec.AddEventParameter("iid", inviteId) - auditRec.AddEventParameter("r", redirect) - auditRec.AddEventParameter("user", user) + audit.AddEventParameter(auditRec, "invite_id", inviteId) + audit.AddEventParameter(auditRec, "redirect", redirect) + audit.AddEventParameterAuditable(auditRec, "user", &user) // No permission check required @@ -463,7 +463,7 @@ func setProfileImage(c *Context, w http.ResponseWriter, r *http.Request) { auditRec := c.MakeAuditRecord("setProfileImage", audit.Fail) defer c.LogAuditRec(auditRec) if imageArray[0] != nil { - auditRec.AddEventParameter("filename", imageArray[0].Filename) + audit.AddEventParameter(auditRec, "filename", imageArray[0].Filename) } user, err := c.App.GetUser(c.Params.UserId) @@ -471,7 +471,7 @@ func setProfileImage(c *Context, w http.ResponseWriter, r *http.Request) { c.SetInvalidURLParam("user_id") return } - auditRec.AddMeta("user", user) + auditRec.AddEventResultState(user) if (user.IsLDAPUser() || (user.IsSAMLUser() && *c.App.Config().SamlSettings.EnableSyncWithLdap)) && *c.App.Config().LdapSettings.PictureAttribute != "" { @@ -510,7 +510,7 @@ func setDefaultProfileImage(c *Context, w http.ResponseWriter, r *http.Request) } auditRec := c.MakeAuditRecord("setDefaultProfileImage", audit.Fail) - auditRec.AddEventParameter("user_id", c.Params.UserId) + audit.AddEventParameter(auditRec, "user_id", c.Params.UserId) defer c.LogAuditRec(auditRec) user, err := c.App.GetUser(c.Params.UserId) @@ -518,7 +518,7 @@ func setDefaultProfileImage(c *Context, w http.ResponseWriter, r *http.Request) c.Err = err return } - auditRec.AddMeta("user", user) + audit.AddEventParameterAuditable(auditRec, "user", user) if err := c.App.SetDefaultProfileImage(c.AppContext, user); err != nil { c.Err = err @@ -1233,21 +1233,22 @@ func updateUser(c *Context, w http.ResponseWriter, r *http.Request) { return } + auditRec := c.MakeAuditRecord("updateUser", audit.Fail) + defer c.LogAuditRec(auditRec) + var user model.User if jsonErr := json.NewDecoder(r.Body).Decode(&user); jsonErr != nil { c.SetInvalidParamWithErr("user", jsonErr) return } + audit.AddEventParameterAuditable(auditRec, "user", &user) // The user being updated in the payload must be the same one as indicated in the URL. if user.Id != c.Params.UserId { c.SetInvalidParam("user_id") return } - auditRec := c.MakeAuditRecord("updateUser", audit.Fail) - defer c.LogAuditRec(auditRec) - // Cannot update a system admin unless user making request is a systemadmin also. if user.IsSystemAdmin() && !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PermissionManageSystem) { c.SetPermissionError(model.PermissionManageSystem) @@ -1264,7 +1265,6 @@ func updateUser(c *Context, w http.ResponseWriter, r *http.Request) { c.Err = err return } - auditRec.AddEventParameter("user", user) auditRec.AddEventPriorState(ouser) auditRec.AddEventObjectType("user") @@ -1322,7 +1322,7 @@ func patchUser(c *Context, w http.ResponseWriter, r *http.Request) { } auditRec := c.MakeAuditRecord("patchUser", audit.Fail) - auditRec.AddEventParameter("user_patch", patch.Auditable()) + audit.AddEventParameterAuditable(auditRec, "user_patch", &patch) defer c.LogAuditRec(auditRec) if !c.App.SessionHasPermissionToUser(*c.AppContext.Session(), c.Params.UserId) { @@ -1399,7 +1399,7 @@ func deleteUser(c *Context, w http.ResponseWriter, r *http.Request) { userId := c.Params.UserId auditRec := c.MakeAuditRecord("deleteUser", audit.Fail) - auditRec.AddEventParameter("user_id", c.Params.UserId) + audit.AddEventParameter(auditRec, "user_id", c.Params.UserId) defer c.LogAuditRec(auditRec) if !c.App.SessionHasPermissionToUser(*c.AppContext.Session(), userId) { @@ -1472,7 +1472,7 @@ func updateUserRoles(c *Context, w http.ResponseWriter, r *http.Request) { } auditRec := c.MakeAuditRecord("updateUserRoles", audit.Fail) - auditRec.AddEventParameter("props", props) + audit.AddEventParameter(auditRec, "roles", newRoles) defer c.LogAuditRec(auditRec) if !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PermissionManageRoles) { @@ -1510,8 +1510,7 @@ func updateUserActive(c *Context, w http.ResponseWriter, r *http.Request) { auditRec := c.MakeAuditRecord("updateUserActive", audit.Fail) defer c.LogAuditRec(auditRec) - auditRec.AddEventParameter("props", props) - auditRec.AddEventParameter("active", active) + audit.AddEventParameter(auditRec, "active", active) // true when you're trying to de-activate yourself isSelfDeactivate := !active && c.Params.UserId == c.AppContext.Session().UserId @@ -1586,7 +1585,7 @@ func updateUserAuth(c *Context, w http.ResponseWriter, r *http.Request) { return } - auditRec.AddEventParameter("user_auth", userAuth.Auditable()) + audit.AddEventParameterAuditable(auditRec, "user_auth", &userAuth) if userAuth.AuthData == nil || *userAuth.AuthData == "" || userAuth.AuthService == "" { c.Err = model.NewAppError("updateUserAuth", "api.user.update_user_auth.invalid_request", nil, "", http.StatusBadRequest) @@ -1634,7 +1633,7 @@ func updateUserMfa(c *Context, w http.ResponseWriter, r *http.Request) { } if user, err := c.App.GetUser(c.Params.UserId); err == nil { - auditRec.AddMeta("user", user) + audit.AddEventParameterAuditable(auditRec, "user", user) } props := model.StringInterfaceFromJSON(r.Body) @@ -1713,7 +1712,7 @@ func updatePassword(c *Context, w http.ResponseWriter, r *http.Request) { var canUpdatePassword bool if user, err := c.App.GetUser(c.Params.UserId); err == nil { - auditRec.AddMeta("user", user) + audit.AddEventParameterAuditable(auditRec, "user", user) if user.IsSystemAdmin() { canUpdatePassword = c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PermissionManageSystem) @@ -1775,7 +1774,6 @@ func resetPassword(c *Context, w http.ResponseWriter, r *http.Request) { auditRec := c.MakeAuditRecord("resetPassword", audit.Fail) defer c.LogAuditRec(auditRec) - auditRec.AddMeta("token", token) c.LogAudit("attempt - token=" + token) if err := c.App.ResetPasswordFromToken(c.AppContext, token, newPassword); err != nil { @@ -1802,7 +1800,7 @@ func sendPasswordReset(c *Context, w http.ResponseWriter, r *http.Request) { auditRec := c.MakeAuditRecord("sendPasswordReset", audit.Fail) defer c.LogAuditRec(auditRec) - auditRec.AddEventParameter("props", props) + audit.AddEventParameter(auditRec, "email", email) sent, err := c.App.SendPasswordReset(email, c.App.GetSiteURL()) if err != nil { @@ -1909,8 +1907,8 @@ func login(c *Context, w http.ResponseWriter, r *http.Request) { auditRec := c.MakeAuditRecord("login", audit.Fail) defer c.LogAuditRec(auditRec) - auditRec.AddEventParameter("login_id", loginId) - auditRec.AddEventParameter("device_id", deviceId) + audit.AddEventParameter(auditRec, "login_id", loginId) + audit.AddEventParameter(auditRec, "device_id", deviceId) c.LogAuditWithUserId(id, "attempt - login_id="+loginId) @@ -1920,7 +1918,7 @@ func login(c *Context, w http.ResponseWriter, r *http.Request) { c.Err = err return } - auditRec.AddMeta("user", user) + auditRec.AddEventResultState(user) if user.IsGuest() { if c.App.Channels().License() == nil { @@ -1995,7 +1993,7 @@ func loginCWS(c *Context, w http.ResponseWriter, r *http.Request) { auditRec := c.MakeAuditRecord("login", audit.Fail) defer c.LogAuditRec(auditRec) - auditRec.AddEventParameter("login_id", loginID) + audit.AddEventParameter(auditRec, "login_id", loginID) user, err := c.App.AuthenticateUserForLogin(c.AppContext, "", loginID, "", "", token, false) if err != nil { c.LogAuditWithUserId("", "failure - login_id="+loginID) @@ -2003,7 +2001,7 @@ func loginCWS(c *Context, w http.ResponseWriter, r *http.Request) { http.Redirect(w, r, *c.App.Config().ServiceSettings.SiteURL, http.StatusFound) return } - auditRec.AddMeta("user", user) + audit.AddEventParameterAuditable(auditRec, "user", user) c.LogAuditWithUserId(user.Id, "authenticated") err = c.App.DoLogin(c.AppContext, w, r, user, "", false, false, false) if err != nil { @@ -2100,6 +2098,7 @@ func revokeSession(c *Context, w http.ResponseWriter, r *http.Request) { c.SetInvalidParam("session_id") return } + audit.AddEventParameter(auditRec, "session_id", sessionId) session, err := c.App.GetSessionById(sessionId) if err != nil { @@ -2107,7 +2106,6 @@ func revokeSession(c *Context, w http.ResponseWriter, r *http.Request) { return } - auditRec.AddEventParameter("props", props) auditRec.AddEventPriorState(session) auditRec.AddEventObjectType("session") @@ -2135,7 +2133,7 @@ func revokeAllSessionsForUser(c *Context, w http.ResponseWriter, r *http.Request auditRec := c.MakeAuditRecord("revokeAllSessionsForUser", audit.Fail) defer c.LogAuditRec(auditRec) - auditRec.AddEventParameter("user_id", c.Params.UserId) + audit.AddEventParameter(auditRec, "user_id", c.Params.UserId) if !c.App.SessionHasPermissionToUser(*c.AppContext.Session(), c.Params.UserId) { c.SetPermissionError(model.PermissionEditOtherUsers) @@ -2184,7 +2182,7 @@ func attachDeviceId(c *Context, w http.ResponseWriter, r *http.Request) { auditRec := c.MakeAuditRecord("attachDeviceId", audit.Fail) defer c.LogAuditRec(auditRec) - auditRec.AddEventParameter("props", props) + audit.AddEventParameter(auditRec, "device_id", deviceId) // A special case where we logout of all other sessions with the same device id if err := c.App.RevokeSessionsForDeviceId(c.AppContext.Session().UserId, deviceId, c.AppContext.Session().Id); err != nil { @@ -2236,11 +2234,11 @@ func getUserAudits(c *Context, w http.ResponseWriter, r *http.Request) { } auditRec := c.MakeAuditRecord("getUserAudits", audit.Fail) - auditRec.AddEventParameter("user_id", c.Params.UserId) + audit.AddEventParameter(auditRec, "user_id", c.Params.UserId) defer c.LogAuditRec(auditRec) if user, err := c.App.GetUser(c.Params.UserId); err == nil { - auditRec.AddMeta("user", user) + audit.AddEventParameterAuditable(auditRec, "user", user) } if !c.App.SessionHasPermissionToUser(*c.AppContext.Session(), c.Params.UserId) { @@ -2299,8 +2297,8 @@ func sendVerificationEmail(c *Context, w http.ResponseWriter, r *http.Request) { auditRec := c.MakeAuditRecord("sendVerificationEmail", audit.Fail) defer c.LogAuditRec(auditRec) - auditRec.AddEventParameter("props", props) - auditRec.AddEventParameter("r", redirect) + audit.AddEventParameter(auditRec, "email", email) + audit.AddEventParameter(auditRec, "redirect", redirect) user, err := c.App.GetUserForLogin("", email) if err != nil { @@ -2308,7 +2306,7 @@ func sendVerificationEmail(c *Context, w http.ResponseWriter, r *http.Request) { ReturnStatusOK(w) return } - auditRec.AddMeta("user", user) + auditRec.AddEventResultState(user) if err = c.App.SendEmailVerification(user, user.Email, redirect); err != nil { // Don't want to leak whether the email is valid or not @@ -2330,7 +2328,7 @@ func switchAccountType(c *Context, w http.ResponseWriter, r *http.Request) { auditRec := c.MakeAuditRecord("switchAccountType", audit.Fail) defer c.LogAuditRec(auditRec) - auditRec.AddEventParameter("switch_request", switchRequest) + audit.AddEventParameterAuditable(auditRec, "switch_request", &switchRequest) link := "" var err *model.AppError @@ -2371,11 +2369,11 @@ func createUserAccessToken(c *Context, w http.ResponseWriter, r *http.Request) { } auditRec := c.MakeAuditRecord("createUserAccessToken", audit.Fail) - auditRec.AddEventParameter("user_id", c.Params.UserId) + audit.AddEventParameter(auditRec, "user_id", c.Params.UserId) defer c.LogAuditRec(auditRec) if user, err := c.App.GetUser(c.Params.UserId); err == nil { - auditRec.AddMeta("user", user) + audit.AddEventParameterAuditable(auditRec, "user", user) } if c.AppContext.Session().IsOAuth { @@ -2546,7 +2544,7 @@ func revokeUserAccessToken(c *Context, w http.ResponseWriter, r *http.Request) { auditRec := c.MakeAuditRecord("revokeUserAccessToken", audit.Fail) defer c.LogAuditRec(auditRec) - auditRec.AddEventParameter("props", props) + audit.AddEventParameter(auditRec, "token_id", tokenId) c.LogAudit("") if !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PermissionRevokeUserAccessToken) { @@ -2561,7 +2559,7 @@ func revokeUserAccessToken(c *Context, w http.ResponseWriter, r *http.Request) { } if user, errGet := c.App.GetUser(accessToken.UserId); errGet == nil { - auditRec.AddMeta("user", user) + audit.AddEventParameterAuditable(auditRec, "user", user) } if !c.App.SessionHasPermissionToUserOrBot(*c.AppContext.Session(), accessToken.UserId) { @@ -2589,7 +2587,7 @@ func disableUserAccessToken(c *Context, w http.ResponseWriter, r *http.Request) } auditRec := c.MakeAuditRecord("disableUserAccessToken", audit.Fail) - auditRec.AddEventParameter("props", props) + audit.AddEventParameter(auditRec, "token_id", tokenId) defer c.LogAuditRec(auditRec) c.LogAudit("") @@ -2606,7 +2604,7 @@ func disableUserAccessToken(c *Context, w http.ResponseWriter, r *http.Request) } if user, errGet := c.App.GetUser(accessToken.UserId); errGet == nil { - auditRec.AddMeta("user", user) + audit.AddEventParameterAuditable(auditRec, "user", user) } if !c.App.SessionHasPermissionToUserOrBot(*c.AppContext.Session(), accessToken.UserId) { @@ -2635,7 +2633,7 @@ func enableUserAccessToken(c *Context, w http.ResponseWriter, r *http.Request) { auditRec := c.MakeAuditRecord("enableUserAccessToken", audit.Fail) defer c.LogAuditRec(auditRec) - auditRec.AddEventParameter("props", props) + audit.AddEventParameter(auditRec, "token_id", tokenId) c.LogAudit("") // No separate permission for this action for now @@ -2651,7 +2649,7 @@ func enableUserAccessToken(c *Context, w http.ResponseWriter, r *http.Request) { } if user, errGet := c.App.GetUser(accessToken.UserId); errGet == nil { - auditRec.AddMeta("user", user) + audit.AddEventParameterAuditable(auditRec, "user", user) } if !c.App.SessionHasPermissionToUserOrBot(*c.AppContext.Session(), accessToken.UserId) { @@ -2673,24 +2671,25 @@ func enableUserAccessToken(c *Context, w http.ResponseWriter, r *http.Request) { func saveUserTermsOfService(c *Context, w http.ResponseWriter, r *http.Request) { props := model.StringInterfaceFromJSON(r.Body) + auditRec := c.MakeAuditRecord("saveUserTermsOfService", audit.Fail) + defer c.LogAuditRec(auditRec) + userId := c.AppContext.Session().UserId termsOfServiceId, ok := props["termsOfServiceId"].(string) if !ok { c.SetInvalidParam("termsOfServiceId") return } + audit.AddEventParameter(auditRec, "terms_of_service_id", termsOfServiceId) accepted, ok := props["accepted"].(bool) if !ok { c.SetInvalidParam("accepted") return } - - auditRec := c.MakeAuditRecord("saveUserTermsOfService", audit.Fail) - defer c.LogAuditRec(auditRec) - auditRec.AddEventParameter("props", props) + audit.AddEventParameter(auditRec, "accepted", accepted) if user, err := c.App.GetUser(userId); err == nil { - auditRec.AddMeta("user", user) + audit.AddEventParameterAuditable(auditRec, "user", user) } if _, err := c.App.GetTermsOfService(termsOfServiceId); err != nil { @@ -2729,7 +2728,7 @@ func promoteGuestToUser(c *Context, w http.ResponseWriter, r *http.Request) { auditRec := c.MakeAuditRecord("promoteGuestToUser", audit.Fail) defer c.LogAuditRec(auditRec) - auditRec.AddEventParameter("user_id", c.Params.UserId) + audit.AddEventParameter(auditRec, "user_id", c.Params.UserId) if !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PermissionPromoteGuest) { c.SetPermissionError(model.PermissionPromoteGuest) @@ -2741,7 +2740,7 @@ func promoteGuestToUser(c *Context, w http.ResponseWriter, r *http.Request) { c.Err = err return } - auditRec.AddMeta("user", user) + auditRec.AddEventResultState(user) if !user.IsGuest() { c.Err = model.NewAppError("Api4.promoteGuestToUser", "api.user.promote_guest_to_user.no_guest.app_error", nil, "", http.StatusNotImplemented) @@ -2781,7 +2780,7 @@ func demoteUserToGuest(c *Context, w http.ResponseWriter, r *http.Request) { } auditRec := c.MakeAuditRecord("demoteUserToGuest", audit.Fail) - auditRec.AddEventParameter("user_id", c.Params.UserId) + audit.AddEventParameter(auditRec, "user_id", c.Params.UserId) defer c.LogAuditRec(auditRec) if !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PermissionDemoteToGuest) { @@ -2800,7 +2799,7 @@ func demoteUserToGuest(c *Context, w http.ResponseWriter, r *http.Request) { return } - auditRec.AddMeta("user", user) + auditRec.AddEventResultState(user) if user.IsGuest() { c.Err = model.NewAppError("Api4.demoteUserToGuest", "api.user.demote_user_to_guest.already_guest.app_error", nil, "", http.StatusNotImplemented) @@ -2859,7 +2858,7 @@ func verifyUserEmailWithoutToken(c *Context, w http.ResponseWriter, r *http.Requ } auditRec := c.MakeAuditRecord("verifyUserEmailWithoutToken", audit.Fail) - auditRec.AddEventParameter("user_id", c.Params.UserId) + audit.AddEventParameter(auditRec, "user_id", c.Params.UserId) defer c.LogAuditRec(auditRec) auditRec.AddMeta("user_id", user.Id) @@ -2894,9 +2893,9 @@ func convertUserToBot(c *Context, w http.ResponseWriter, r *http.Request) { } auditRec := c.MakeAuditRecord("convertUserToBot", audit.Fail) - auditRec.AddEventParameter("user_id", c.Params.UserId) + audit.AddEventParameter(auditRec, "user_id", c.Params.UserId) defer c.LogAuditRec(auditRec) - auditRec.AddMeta("user", user) + audit.AddEventParameterAuditable(auditRec, "user", user) if !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PermissionManageSystem) { c.SetPermissionError(model.PermissionManageSystem) @@ -2997,7 +2996,9 @@ func migrateAuthToLDAP(c *Context, w http.ResponseWriter, r *http.Request) { auditRec := c.MakeAuditRecord("migrateAuthToLdap", audit.Fail) defer c.LogAuditRec(auditRec) - auditRec.AddEventParameter("props", props) + audit.AddEventParameter(auditRec, "from", from) + audit.AddEventParameter(auditRec, "force", force) + audit.AddEventParameter(auditRec, "match_field", matchField) if !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PermissionManageSystem) { c.SetPermissionError(model.PermissionManageSystem) @@ -3054,7 +3055,9 @@ func migrateAuthToSaml(c *Context, w http.ResponseWriter, r *http.Request) { auditRec := c.MakeAuditRecord("migrateAuthToSaml", audit.Fail) defer c.LogAuditRec(auditRec) - auditRec.AddEventParameter("props", props) + audit.AddEventParameter(auditRec, "from", from) + audit.AddEventParameter(auditRec, "auto", auto) + audit.AddEventParameter(auditRec, "users_map", usersMap) if !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PermissionManageSystem) { c.SetPermissionError(model.PermissionManageSystem) @@ -3193,10 +3196,10 @@ func updateReadStateThreadByUser(c *Context, w http.ResponseWriter, r *http.Requ auditRec := c.MakeAuditRecord("updateReadStateThreadByUser", audit.Fail) defer c.LogAuditRec(auditRec) - auditRec.AddEventParameter("user_id", c.Params.UserId) - auditRec.AddEventParameter("thread_id", c.Params.ThreadId) - auditRec.AddEventParameter("team_id", c.Params.TeamId) - auditRec.AddEventParameter("timestamp", c.Params.Timestamp) + audit.AddEventParameter(auditRec, "user_id", c.Params.UserId) + audit.AddEventParameter(auditRec, "thread_id", c.Params.ThreadId) + audit.AddEventParameter(auditRec, "team_id", c.Params.TeamId) + audit.AddEventParameter(auditRec, "timestamp", c.Params.Timestamp) if !c.App.SessionHasPermissionToUser(*c.AppContext.Session(), c.Params.UserId) { c.SetPermissionError(model.PermissionEditOtherUsers) return @@ -3223,10 +3226,10 @@ func setUnreadThreadByPostId(c *Context, w http.ResponseWriter, r *http.Request) auditRec := c.MakeAuditRecord("setUnreadThreadByPostId", audit.Fail) defer c.LogAuditRec(auditRec) - auditRec.AddEventParameter("user_id", c.Params.UserId) - auditRec.AddEventParameter("thread_id", c.Params.ThreadId) - auditRec.AddEventParameter("team_id", c.Params.TeamId) - auditRec.AddEventParameter("post_id", c.Params.PostId) + audit.AddEventParameter(auditRec, "user_id", c.Params.UserId) + audit.AddEventParameter(auditRec, "thread_id", c.Params.ThreadId) + audit.AddEventParameter(auditRec, "team_id", c.Params.TeamId) + audit.AddEventParameter(auditRec, "post_id", c.Params.PostId) if !c.App.SessionHasPermissionToUser(*c.AppContext.Session(), c.Params.UserId) { c.SetPermissionError(model.PermissionEditOtherUsers) @@ -3259,9 +3262,9 @@ func unfollowThreadByUser(c *Context, w http.ResponseWriter, r *http.Request) { auditRec := c.MakeAuditRecord("unfollowThreadByUser", audit.Fail) defer c.LogAuditRec(auditRec) - auditRec.AddEventParameter("user_id", c.Params.UserId) - auditRec.AddEventParameter("thread_id", c.Params.ThreadId) - auditRec.AddEventParameter("team_id", c.Params.TeamId) + audit.AddEventParameter(auditRec, "user_id", c.Params.UserId) + audit.AddEventParameter(auditRec, "thread_id", c.Params.ThreadId) + audit.AddEventParameter(auditRec, "team_id", c.Params.TeamId) if !c.App.SessionHasPermissionToUser(*c.AppContext.Session(), c.Params.UserId) { c.SetPermissionError(model.PermissionEditOtherUsers) @@ -3287,9 +3290,9 @@ func followThreadByUser(c *Context, w http.ResponseWriter, r *http.Request) { auditRec := c.MakeAuditRecord("followThreadByUser", audit.Fail) defer c.LogAuditRec(auditRec) - auditRec.AddEventParameter("user_id", c.Params.UserId) - auditRec.AddEventParameter("thread_id", c.Params.ThreadId) - auditRec.AddEventParameter("team_id", c.Params.TeamId) + audit.AddEventParameter(auditRec, "user_id", c.Params.UserId) + audit.AddEventParameter(auditRec, "thread_id", c.Params.ThreadId) + audit.AddEventParameter(auditRec, "team_id", c.Params.TeamId) if !c.App.SessionHasPermissionToUser(*c.AppContext.Session(), c.Params.UserId) { c.SetPermissionError(model.PermissionEditOtherUsers) @@ -3319,8 +3322,8 @@ func updateReadStateAllThreadsByUser(c *Context, w http.ResponseWriter, r *http. auditRec := c.MakeAuditRecord("updateReadStateAllThreadsByUser", audit.Fail) defer c.LogAuditRec(auditRec) - auditRec.AddEventParameter("user_id", c.Params.UserId) - auditRec.AddEventParameter("team_id", c.Params.TeamId) + audit.AddEventParameter(auditRec, "user_id", c.Params.UserId) + audit.AddEventParameter(auditRec, "team_id", c.Params.TeamId) if !c.App.SessionHasPermissionToUser(*c.AppContext.Session(), c.Params.UserId) { c.SetPermissionError(model.PermissionEditOtherUsers) diff --git a/api4/user_local.go b/api4/user_local.go index 79578f2484..7ee5932455 100644 --- a/api4/user_local.go +++ b/api4/user_local.go @@ -320,7 +320,7 @@ func localDeleteUser(c *Context, w http.ResponseWriter, r *http.Request) { c.Err = err return } - auditRec.AddEventParameter("user_id", c.Params.UserId) + audit.AddEventParameter(auditRec, "user_id", c.Params.UserId) auditRec.AddEventPriorState(user) auditRec.AddEventObjectType("user") diff --git a/api4/user_test.go b/api4/user_test.go index 7280340ec1..fdfb5cf69c 100644 --- a/api4/user_test.go +++ b/api4/user_test.go @@ -6,6 +6,7 @@ package api4 import ( "encoding/json" "fmt" + "io" "net/http" "net/url" "os" @@ -113,6 +114,45 @@ func TestCreateUser(t *testing.T) { }, "Should not be able to create two users with the same email but spaces in it") } +func TestCreateUserAudit(t *testing.T) { + logFile, err := os.CreateTemp("", "adv.log") + require.NoError(t, err) + defer os.Remove(logFile.Name()) + + os.Setenv("MM_EXPERIMENTALAUDITSETTINGS_FILEENABLED", "true") + os.Setenv("MM_EXPERIMENTALAUDITSETTINGS_FILENAME", logFile.Name()) + defer os.Unsetenv("MM_EXPERIMENTALAUDITSETTINGS_FILEENABLED") + defer os.Unsetenv("MM_EXPERIMENTALAUDITSETTINGS_FILENAME") + + options := []app.Option{app.WithLicense(model.NewTestLicense("advanced_logging"))} + th := SetupWithServerOptions(t, options) + defer th.TearDown() + + email := th.GenerateTestEmail() + password := "this_is_the_password" + user := model.User{ + Email: email, + Password: password, + Username: GenerateTestUsername(), + } + _, resp, err := th.Client.CreateUser(&user) + require.NoError(t, err) + CheckCreatedStatus(t, resp) + + // Forcing a flush before attempting to read log's content. + err = th.Server.Audit.Flush() + require.NoError(t, err) + + require.NoError(t, logFile.Sync()) + + data, err := io.ReadAll(logFile) + require.NoError(t, err) + require.NotEmpty(t, data) + + require.Contains(t, string(data), email) + require.NotContains(t, string(data), password) +} + func TestCreateUserInputFilter(t *testing.T) { th := Setup(t) defer th.TearDown() @@ -5867,6 +5907,40 @@ func TestUpdatePassword(t *testing.T) { }) } +func TestUpdatePasswordAudit(t *testing.T) { + logFile, err := os.CreateTemp("", "adv.log") + require.NoError(t, err) + defer os.Remove(logFile.Name()) + + os.Setenv("MM_EXPERIMENTALAUDITSETTINGS_FILEENABLED", "true") + os.Setenv("MM_EXPERIMENTALAUDITSETTINGS_FILENAME", logFile.Name()) + defer os.Unsetenv("MM_EXPERIMENTALAUDITSETTINGS_FILEENABLED") + defer os.Unsetenv("MM_EXPERIMENTALAUDITSETTINGS_FILENAME") + + options := []app.Option{app.WithLicense(model.NewTestLicense("advanced_logging"))} + th := SetupWithServerOptions(t, options) + defer th.TearDown() + + password := "this_is_the_password" + th.LoginBasic() + resp, err := th.Client.UpdatePassword(th.BasicUser.Id, th.BasicUser.Password, password) + require.NoError(t, err) + CheckOKStatus(t, resp) + + // Forcing a flush before attempting to read log's content. + err = th.Server.Audit.Flush() + require.NoError(t, err) + + require.NoError(t, logFile.Sync()) + + data, err := io.ReadAll(logFile) + require.NoError(t, err) + require.NotEmpty(t, data) + + require.Contains(t, string(data), th.BasicUser.Id) + require.NotContains(t, string(data), password) +} + func TestGetThreadsForUser(t *testing.T) { os.Setenv("MM_FEATUREFLAGS_POSTPRIORITY", "true") defer os.Unsetenv("MM_FEATUREFLAGS_POSTPRIORITY") diff --git a/api4/webhook.go b/api4/webhook.go index 3f871d9952..273f55ed53 100644 --- a/api4/webhook.go +++ b/api4/webhook.go @@ -42,8 +42,8 @@ func createIncomingHook(c *Context, w http.ResponseWriter, r *http.Request) { auditRec := c.MakeAuditRecord("createIncomingHook", audit.Fail) defer c.LogAuditRec(auditRec) - auditRec.AddEventParameter("incoming_webhook", hook) - auditRec.AddMeta("channel", channel) + audit.AddEventParameterAuditable(auditRec, "incoming_webhook", &hook) + audit.AddEventParameterAuditable(auditRec, "channel", channel) c.LogAudit("attempt") if !c.App.SessionHasPermissionToTeam(*c.AppContext.Session(), channel.TeamId, model.PermissionManageIncomingWebhooks) { @@ -109,8 +109,8 @@ func updateIncomingHook(c *Context, w http.ResponseWriter, r *http.Request) { } auditRec := c.MakeAuditRecord("updateIncomingHook", audit.Fail) - auditRec.AddEventParameter("hook_id", c.Params.HookId) - auditRec.AddEventParameter("updated_hook", updatedHook) + audit.AddEventParameter(auditRec, "hook_id", c.Params.HookId) + audit.AddEventParameterAuditable(auditRec, "updated_hook", &updatedHook) defer c.LogAuditRec(auditRec) c.LogAudit("attempt") @@ -246,7 +246,7 @@ func getIncomingHook(c *Context, w http.ResponseWriter, r *http.Request) { auditRec := c.MakeAuditRecord("getIncomingHook", audit.Fail) defer c.LogAuditRec(auditRec) - auditRec.AddEventParameter("hook_id", c.Params.HookId) + audit.AddEventParameter(auditRec, "hook_id", c.Params.HookId) auditRec.AddMeta("hook_id", hook.Id) auditRec.AddMeta("hook_display", hook.DisplayName) auditRec.AddMeta("channel_id", hook.ChannelId) @@ -306,7 +306,7 @@ func deleteIncomingHook(c *Context, w http.ResponseWriter, r *http.Request) { auditRec := c.MakeAuditRecord("deleteIncomingHook", audit.Fail) defer c.LogAuditRec(auditRec) - auditRec.AddEventParameter("hook_id", c.Params.HookId) + audit.AddEventParameter(auditRec, "hook_id", c.Params.HookId) auditRec.AddMeta("hook_id", hook.Id) auditRec.AddMeta("hook_display", hook.DisplayName) auditRec.AddMeta("channel_id", channel.Id) @@ -357,7 +357,7 @@ func updateOutgoingHook(c *Context, w http.ResponseWriter, r *http.Request) { auditRec := c.MakeAuditRecord("updateOutgoingHook", audit.Fail) defer c.LogAuditRec(auditRec) - auditRec.AddEventParameter("updated_hook", updatedHook) + audit.AddEventParameterAuditable(auditRec, "updated_hook", &updatedHook) c.LogAudit("attempt") oldHook, err := c.App.GetOutgoingWebhook(c.Params.HookId) @@ -410,7 +410,7 @@ func createOutgoingHook(c *Context, w http.ResponseWriter, r *http.Request) { } auditRec := c.MakeAuditRecord("createOutgoingHook", audit.Fail) - auditRec.AddEventParameter("hook", hook) + audit.AddEventParameterAuditable(auditRec, "hook", &hook) defer c.LogAuditRec(auditRec) c.LogAudit("attempt") @@ -530,7 +530,7 @@ func getOutgoingHook(c *Context, w http.ResponseWriter, r *http.Request) { auditRec := c.MakeAuditRecord("getOutgoingHook", audit.Fail) defer c.LogAuditRec(auditRec) - auditRec.AddEventParameter("hook_id", c.Params.HookId) + audit.AddEventParameter(auditRec, "hook_id", c.Params.HookId) auditRec.AddMeta("hook_id", hook.Id) auditRec.AddMeta("hook_display", hook.DisplayName) auditRec.AddMeta("channel_id", hook.ChannelId) @@ -617,7 +617,7 @@ func deleteOutgoingHook(c *Context, w http.ResponseWriter, r *http.Request) { auditRec := c.MakeAuditRecord("deleteOutgoingHook", audit.Fail) defer c.LogAuditRec(auditRec) - auditRec.AddEventParameter("hook_id", c.Params.HookId) + audit.AddEventParameter(auditRec, "hook_id", c.Params.HookId) auditRec.AddMeta("hook_id", hook.Id) auditRec.AddMeta("hook_display", hook.DisplayName) auditRec.AddMeta("channel_id", hook.ChannelId) diff --git a/api4/webhook_local.go b/api4/webhook_local.go index cadffbd41e..4d90ba751f 100644 --- a/api4/webhook_local.go +++ b/api4/webhook_local.go @@ -51,8 +51,8 @@ func localCreateIncomingHook(c *Context, w http.ResponseWriter, r *http.Request) auditRec := c.MakeAuditRecord("localCreateIncomingHook", audit.Fail) defer c.LogAuditRec(auditRec) - auditRec.AddEventParameter("hook", hook) - auditRec.AddMeta("channel", channel) + audit.AddEventParameterAuditable(auditRec, "hook", &hook) + audit.AddEventParameterAuditable(auditRec, "channel", channel) c.LogAudit("attempt") incomingHook, err := c.App.CreateIncomingWebhookForChannel(hook.UserId, channel, &hook) @@ -81,7 +81,7 @@ func localCreateOutgoingHook(c *Context, w http.ResponseWriter, r *http.Request) auditRec := c.MakeAuditRecord("createOutgoingHook", audit.Fail) defer c.LogAuditRec(auditRec) - auditRec.AddEventParameter("hook", hook) + audit.AddEventParameterAuditable(auditRec, "hook", &hook) c.LogAudit("attempt") if hook.CreatorId == "" { diff --git a/app/session.go b/app/session.go index 5b69258baf..bbfc830d6a 100644 --- a/app/session.go +++ b/app/session.go @@ -267,7 +267,7 @@ func (a *App) ExtendSessionExpiryIfNeeded(session *model.Session) bool { auditRec := a.MakeAuditRecord("extendSessionExpiry", audit.Fail) defer a.LogAuditRec(auditRec, nil) - auditRec.AddMeta("session", session) + auditRec.AddEventPriorState(session) newExpiry := now + sessionLength if err := a.ch.srv.platform.ExtendSessionExpiry(session, newExpiry); err != nil { @@ -280,7 +280,7 @@ func (a *App) ExtendSessionExpiryIfNeeded(session *model.Session) bool { mlog.Int64("newExpiry", newExpiry), mlog.Int64("session_length", sessionLength)) auditRec.Success() - auditRec.AddMeta("extended_session", session) + auditRec.AddEventResultState(session) return true } diff --git a/audit/record.go b/audit/record.go index e5fbafa3ae..2e12b1d7cb 100644 --- a/audit/record.go +++ b/audit/record.go @@ -59,16 +59,35 @@ func (rec *Record) Fail() { } // AddEventParameter adds a parameter, e.g. query or post body, to the event -func (rec *Record) AddEventParameter(key string, val interface{}) { +func AddEventParameter[T string | bool | int | int64 | []string | map[string]string](rec *Record, key string, val T) { if rec.EventData.Parameters == nil { rec.EventData.Parameters = make(map[string]interface{}) } - if auditableVal, ok := val.(Auditable); ok { - rec.EventData.Parameters[key] = auditableVal.Auditable() - } else { - rec.EventData.Parameters[key] = val + rec.EventData.Parameters[key] = val +} + +// AddEventParameterAuditable adds an object that is of type Auditable to the event +func AddEventParameterAuditable(rec *Record, key string, val Auditable) { + if rec.EventData.Parameters == nil { + rec.EventData.Parameters = make(map[string]interface{}) } + + rec.EventData.Parameters[key] = val.Auditable() +} + +// AddEventParameterAuditableArray adds an array of objects of type Auditable to the event +func AddEventParameterAuditableArray[T Auditable](rec *Record, key string, val []T) { + if rec.EventData.Parameters == nil { + rec.EventData.Parameters = make(map[string]interface{}) + } + + processedAuditables := make([]map[string]interface{}, 0, len(val)) + for _, auditableVal := range val { + processedAuditables = append(processedAuditables, auditableVal.Auditable()) + } + + rec.EventData.Parameters[key] = processedAuditables } // AddEventPriorState adds the prior state of the modified object to the audit record diff --git a/model/bot.go b/model/bot.go index bea54a4327..dd2b6d65fa 100644 --- a/model/bot.go +++ b/model/bot.go @@ -54,6 +54,14 @@ type BotPatch struct { Description *string `json:"description"` } +func (b *BotPatch) Auditable() map[string]interface{} { + return map[string]interface{}{ + "username": b.Username, + "display_name": b.DisplayName, + "description": b.Description, + } +} + // BotGetOptions acts as a filter on bulk bot fetching queries. type BotGetOptions struct { OwnerId string diff --git a/model/channel.go b/model/channel.go index 0ca11c75e6..40dcb834fa 100644 --- a/model/channel.go +++ b/model/channel.go @@ -142,6 +142,13 @@ type ChannelModerationPatch struct { Roles *ChannelModeratedRolesPatch `json:"roles"` } +func (c *ChannelModerationPatch) Auditable() map[string]interface{} { + return map[string]interface{}{ + "name": c.Name, + "roles": c.Roles, + } +} + type ChannelModeratedRolesPatch struct { Guests *bool `json:"guests"` Members *bool `json:"members"` diff --git a/model/file_info.go b/model/file_info.go index 4aa0a84fa2..a45b36f657 100644 --- a/model/file_info.go +++ b/model/file_info.go @@ -59,6 +59,21 @@ type FileInfo struct { Archived bool `json:"archived"` } +func (fi *FileInfo) Auditable() map[string]interface{} { + return map[string]interface{}{ + "id": fi.Id, + "creator_id": fi.CreatorId, + "post_id": fi.PostId, + "channel_id": fi.ChannelId, + "create_at": fi.CreateAt, + "update_at": fi.UpdateAt, + "delete_at": fi.DeleteAt, + "name": fi.Name, + "extension": fi.Extension, + "size": fi.Size, + } +} + func (fi *FileInfo) PreSave() { if fi.Id == "" { fi.Id = NewId() diff --git a/model/group.go b/model/group.go index 530eab88f7..6a56b52e8a 100644 --- a/model/group.go +++ b/model/group.go @@ -66,6 +66,21 @@ type GroupWithUserIds struct { UserIds []string `json:"user_ids"` } +func (group *GroupWithUserIds) Auditable() map[string]interface{} { + return map[string]interface{}{ + "id": group.Id, + "source": group.Source, + "remote_id": group.RemoteId, + "create_at": group.CreateAt, + "update_at": group.UpdateAt, + "delete_at": group.DeleteAt, + "has_syncables": group.HasSyncables, + "member_count": group.MemberCount, + "allow_reference": group.AllowReference, + "user_ids": group.UserIds, + } +} + type GroupWithSchemeAdmin struct { Group SchemeAdmin *bool `db:"SyncableSchemeAdmin" json:"scheme_admin,omitempty"` @@ -138,6 +153,12 @@ type GroupModifyMembers struct { UserIds []string `json:"user_ids"` } +func (group *GroupModifyMembers) Auditable() map[string]interface{} { + return map[string]interface{}{ + "user_ids": group.UserIds, + } +} + func (group *Group) Patch(patch *GroupPatch) { if patch.Name != nil { group.Name = patch.Name diff --git a/model/group_syncable.go b/model/group_syncable.go index e876a4c55f..83df73bf12 100644 --- a/model/group_syncable.go +++ b/model/group_syncable.go @@ -153,6 +153,13 @@ type GroupSyncablePatch struct { SchemeAdmin *bool `json:"scheme_admin"` } +func (syncable *GroupSyncablePatch) Auditable() map[string]interface{} { + return map[string]interface{}{ + "auto_add": syncable.AutoAdd, + "scheme_admin": syncable.SchemeAdmin, + } +} + func (syncable *GroupSyncable) Patch(patch *GroupSyncablePatch) { if patch.AutoAdd != nil { syncable.AutoAdd = *patch.AutoAdd diff --git a/model/guest_invite.go b/model/guest_invite.go index 5103ccd1b1..d187635beb 100644 --- a/model/guest_invite.go +++ b/model/guest_invite.go @@ -13,6 +13,13 @@ type GuestsInvite struct { Message string `json:"message"` } +func (i *GuestsInvite) Auditable() map[string]interface{} { + return map[string]interface{}{ + "emails": i.Emails, + "channels": i.Channels, + } +} + // IsValid validates the user and returns an error if it isn't configured // correctly. func (i *GuestsInvite) IsValid() *AppError { diff --git a/model/member_invite.go b/model/member_invite.go index 94258dbeb3..4aaf836ed2 100644 --- a/model/member_invite.go +++ b/model/member_invite.go @@ -14,6 +14,13 @@ type MemberInvite struct { Message string `json:"message"` } +func (i *MemberInvite) Auditable() map[string]interface{} { + return map[string]interface{}{ + "emails": i.Emails, + "channel_ids": i.ChannelIds, + } +} + // IsValid validates that the invitation info is loaded correctly and with the correct structure func (i *MemberInvite) IsValid() *AppError { if len(i.Emails) == 0 { diff --git a/model/onboarding.go b/model/onboarding.go index 9c83e37642..797bea7c1d 100644 --- a/model/onboarding.go +++ b/model/onboarding.go @@ -13,6 +13,12 @@ type CompleteOnboardingRequest struct { InstallPlugins []string `json:"install_plugins"` // InstallPlugins is a list of plugins to be installed } +func (r *CompleteOnboardingRequest) Auditable() map[string]interface{} { + return map[string]interface{}{ + "install_plugins": r.InstallPlugins, + } +} + // CompleteOnboardingRequest decodes a json-encoded request from the given io.Reader. func CompleteOnboardingRequestFromReader(reader io.Reader) (*CompleteOnboardingRequest, error) { var r *CompleteOnboardingRequest diff --git a/model/remote_cluster.go b/model/remote_cluster.go index 1ca76c7eb1..5b976f3317 100644 --- a/model/remote_cluster.go +++ b/model/remote_cluster.go @@ -41,6 +41,19 @@ type RemoteCluster struct { CreatorId string `json:"creator_id"` } +func (rc *RemoteCluster) Auditable() map[string]interface{} { + return map[string]interface{}{ + "remote_id": rc.RemoteId, + "remote_team_id": rc.RemoteTeamId, + "name": rc.Name, + "display_name": rc.DisplayName, + "site_url": rc.SiteURL, + "create_at": rc.CreateAt, + "last_ping_at": rc.LastPingAt, + "creator_id": rc.CreatorId, + } +} + func (rc *RemoteCluster) PreSave() { if rc.RemoteId == "" { rc.RemoteId = NewId() @@ -154,6 +167,13 @@ type RemoteClusterFrame struct { Msg RemoteClusterMsg `json:"msg"` } +func (f *RemoteClusterFrame) Auditable() map[string]interface{} { + return map[string]interface{}{ + "remote_id": f.RemoteId, + "msg": f.Msg, + } +} + func (f *RemoteClusterFrame) IsValid() *AppError { if !IsValidId(f.RemoteId) { return NewAppError("RemoteClusterFrame.IsValid", "api.remote_cluster.invalid_id.app_error", nil, "RemoteId="+f.RemoteId, http.StatusBadRequest) diff --git a/model/role.go b/model/role.go index b4a1825537..2c7a8fbf7b 100644 --- a/model/role.go +++ b/model/role.go @@ -437,6 +437,12 @@ type RolePatch struct { Permissions *[]string `json:"permissions"` } +func (r *RolePatch) Auditable() map[string]interface{} { + return map[string]interface{}{ + "permissions": r.Permissions, + } +} + type RolePermissions struct { RoleID string Permissions []string diff --git a/model/scheme.go b/model/scheme.go index c48621980b..a231f0cc4f 100644 --- a/model/scheme.go +++ b/model/scheme.go @@ -68,10 +68,24 @@ type SchemePatch struct { Description *string `json:"description"` } +func (scheme *SchemePatch) Auditable() map[string]interface{} { + return map[string]interface{}{ + "name": scheme.Name, + "display_name": scheme.DisplayName, + "description": scheme.Description, + } +} + type SchemeIDPatch struct { SchemeID *string `json:"scheme_id"` } +func (p *SchemeIDPatch) Auditable() map[string]interface{} { + return map[string]interface{}{ + "scheme_id": p.SchemeID, + } +} + // SchemeConveyor is used for importing and exporting a Scheme and its associated Roles. type SchemeConveyor struct { Name string `json:"name"` diff --git a/model/session.go b/model/session.go index de9558fde6..0cdcca3fab 100644 --- a/model/session.go +++ b/model/session.go @@ -70,7 +70,6 @@ func (s *Session) Auditable() map[string]interface{} { "is_oauth": s.IsOAuth, "expired_notify": s.ExpiredNotify, "local": s.Local, - // TODO: props and members? } } diff --git a/model/switch_request.go b/model/switch_request.go index 70694cb1a4..f59115f5ba 100644 --- a/model/switch_request.go +++ b/model/switch_request.go @@ -13,6 +13,15 @@ type SwitchRequest struct { LdapLoginId string `json:"ldap_id"` } +func (o *SwitchRequest) Auditable() map[string]interface{} { + return map[string]interface{}{ + "current_service": o.CurrentService, + "new_service": o.NewService, + "email": o.Email, + "ldap_login_id": o.LdapLoginId, + } +} + func (o *SwitchRequest) EmailToOAuth() bool { return o.CurrentService == UserAuthServiceEmail && (o.NewService == UserAuthServiceSaml || diff --git a/model/team.go b/model/team.go index 07b0d061aa..bd8b7aa898 100644 --- a/model/team.go +++ b/model/team.go @@ -70,6 +70,14 @@ type TeamPatch struct { CloudLimitsArchived *bool `json:"cloud_limits_archived"` } +func (o *TeamPatch) Auditable() map[string]interface{} { + return map[string]interface{}{ + "allow_open_invite": o.AllowOpenInvite, + "group_constrained": o.GroupConstrained, + "cloud_limits_archived": o.CloudLimitsArchived, + } +} + type TeamForExport struct { Team SchemeName *string diff --git a/model/upload_session.go b/model/upload_session.go index 4dacb53013..9181c3e3e9 100644 --- a/model/upload_session.go +++ b/model/upload_session.go @@ -47,6 +47,19 @@ type UploadSession struct { ReqFileId string `json:"req_file_id"` } +func (us *UploadSession) Auditable() map[string]interface{} { + return map[string]interface{}{ + "id": us.Id, + "type": us.Type, + "user_id": us.UserId, + "channel_id": us.ChannelId, + "filename": us.Filename, + "file_size": us.FileSize, + "remote_id": us.RemoteId, + "ReqFileId": us.ReqFileId, + } +} + // PreSave is a utility function used to fill required information. func (us *UploadSession) PreSave() { if us.Id == "" {