MM-22273 New auditing system (phase 1) (#13967)

* New auditing API outputting to syslog via TLS

* New config section for specifying remote syslog server IP, port, and cert.

* Legacy audit API retained for access history feature
Этот коммит содержится в:
Doug Lauder
2020-03-12 15:50:21 -04:00
коммит произвёл GitHub
родитель bd1e7f2265
Коммит 4ac0619c90
156 изменённых файлов: 16991 добавлений и 49 удалений

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

@@ -15,6 +15,7 @@ import (
"strconv"
"strings"
"github.com/mattermost/mattermost-server/v5/audit"
"github.com/mattermost/mattermost-server/v5/model"
)
@@ -81,6 +82,11 @@ func createTeam(c *Context, w http.ResponseWriter, r *http.Request) {
}
team.Email = strings.ToLower(team.Email)
auditRec := c.MakeAuditRecord("createTeam", audit.Fail)
defer c.LogAuditRec(auditRec)
auditRec.AddMeta("team_name", team.Name)
auditRec.AddMeta("team_display", team.DisplayName)
if !c.App.SessionHasPermissionTo(*c.App.Session(), model.PERMISSION_CREATE_TEAM) {
c.Err = model.NewAppError("createTeam", "api.team.is_team_creation_allowed.disabled.app_error", nil, "", http.StatusForbidden)
return
@@ -94,6 +100,9 @@ func createTeam(c *Context, w http.ResponseWriter, r *http.Request) {
// Don't sanitize the team here since the user will be a team admin and their session won't reflect that yet
auditRec.Success()
auditRec.AddMeta("team_id", rteam.Id)
w.WriteHeader(http.StatusCreated)
w.Write([]byte(rteam.ToJson()))
}
@@ -160,6 +169,12 @@ func updateTeam(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
auditRec := c.MakeAuditRecord("updateTeam", audit.Fail)
defer c.LogAuditRec(auditRec)
auditRec.AddMeta("team_id", c.Params.TeamId)
auditRec.AddMeta("team_name", team.Name)
auditRec.AddMeta("team_display", team.DisplayName)
if !c.App.SessionHasPermissionToTeam(*c.App.Session(), c.Params.TeamId, model.PERMISSION_MANAGE_TEAM) {
c.SetPermissionError(model.PERMISSION_MANAGE_TEAM)
return
@@ -171,6 +186,8 @@ func updateTeam(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
auditRec.Success()
c.App.SanitizeTeam(*c.App.Session(), updatedTeam)
w.Write([]byte(updatedTeam.ToJson()))
}
@@ -188,6 +205,10 @@ func patchTeam(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
auditRec := c.MakeAuditRecord("patchTeam", audit.Fail)
defer c.LogAuditRec(auditRec)
auditRec.AddMeta("team_id", c.Params.TeamId)
if !c.App.SessionHasPermissionToTeam(*c.App.Session(), c.Params.TeamId, model.PERMISSION_MANAGE_TEAM) {
c.SetPermissionError(model.PERMISSION_MANAGE_TEAM)
return
@@ -202,7 +223,11 @@ func patchTeam(c *Context, w http.ResponseWriter, r *http.Request) {
c.App.SanitizeTeam(*c.App.Session(), patchedTeam)
auditRec.Success()
auditRec.AddMeta("team_name", patchedTeam.Name)
auditRec.AddMeta("team_display", patchedTeam.DisplayName)
c.LogAudit("")
w.Write([]byte(patchedTeam.ToJson()))
}
@@ -217,6 +242,10 @@ func regenerateTeamInviteId(c *Context, w http.ResponseWriter, r *http.Request)
return
}
auditRec := c.MakeAuditRecord("regenerateTeamInviteId", audit.Fail)
defer c.LogAuditRec(auditRec)
auditRec.AddMeta("team_id", c.Params.TeamId)
patchedTeam, err := c.App.RegenerateTeamInviteId(c.Params.TeamId)
if err != nil {
c.Err = err
@@ -225,7 +254,11 @@ func regenerateTeamInviteId(c *Context, w http.ResponseWriter, r *http.Request)
c.App.SanitizeTeam(*c.App.Session(), patchedTeam)
auditRec.Success()
auditRec.AddMeta("team_name", patchedTeam.Name)
auditRec.AddMeta("team_display", patchedTeam.DisplayName)
c.LogAudit("")
w.Write([]byte(patchedTeam.ToJson()))
}
@@ -240,6 +273,10 @@ func deleteTeam(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
auditRec := c.MakeAuditRecord("deleteTeam", audit.Fail)
defer c.LogAuditRec(auditRec)
auditRec.AddMeta("team_id", c.Params.TeamId)
var err *model.AppError
if c.Params.Permanent && *c.App.Config().ServiceSettings.EnableAPITeamDeletion {
err = c.App.PermanentDeleteTeamId(c.Params.TeamId)
@@ -252,6 +289,7 @@ func deleteTeam(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
auditRec.Success()
ReturnStatusOK(w)
}
@@ -438,6 +476,11 @@ func addTeamMember(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
auditRec := c.MakeAuditRecord("addTeamMember", audit.Fail)
defer c.LogAuditRec(auditRec)
auditRec.AddMeta("team_id", c.Params.TeamId)
auditRec.AddMeta("add_user_id", member.UserId)
if member.UserId == c.App.Session().UserId {
var team *model.Team
team, err = c.App.GetTeam(member.TeamId)
@@ -466,6 +509,8 @@ func addTeamMember(c *Context, w http.ResponseWriter, r *http.Request) {
c.Err = err
return
}
auditRec.AddMeta("team_name", team.Name)
auditRec.AddMeta("team_display", team.DisplayName)
if team.IsGroupConstrained() {
nonMembers, err := c.App.FilterNonGroupTeamMembers([]string{member.UserId}, team)
@@ -490,6 +535,8 @@ func addTeamMember(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
auditRec.Success()
w.WriteHeader(http.StatusCreated)
w.Write([]byte(member.ToJson()))
}
@@ -501,6 +548,10 @@ func addUserToTeamFromInvite(c *Context, w http.ResponseWriter, r *http.Request)
var member *model.TeamMember
var err *model.AppError
auditRec := c.MakeAuditRecord("addUserToTeamFromInvite", audit.Fail)
defer c.LogAuditRec(auditRec)
auditRec.AddMeta("invite_id", inviteId)
if len(tokenId) > 0 {
member, err = c.App.AddTeamMemberByToken(c.App.Session().UserId, tokenId)
} else if len(inviteId) > 0 {
@@ -519,6 +570,11 @@ func addUserToTeamFromInvite(c *Context, w http.ResponseWriter, r *http.Request)
return
}
auditRec.Success()
if member != nil {
auditRec.AddMeta("add_user_id", member.UserId)
}
w.WriteHeader(http.StatusCreated)
w.Write([]byte(member.ToJson()))
}
@@ -544,16 +600,24 @@ func addTeamMembers(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
auditRec := c.MakeAuditRecord("addTeamMembers", audit.Fail)
defer c.LogAuditRec(auditRec)
auditRec.AddMeta("team_id", c.Params.TeamId)
auditRec.AddMeta("count", len(members))
var memberIDs []string
for _, member := range members {
memberIDs = append(memberIDs, member.UserId)
}
auditRec.AddMeta("user_ids", memberIDs)
team, err := c.App.GetTeam(c.Params.TeamId)
if err != nil {
c.Err = err
return
}
auditRec.AddMeta("team_name", team.Name)
auditRec.AddMeta("team_display", team.DisplayName)
if team.IsGroupConstrained() {
nonMembers, err := c.App.FilterNonGroupTeamMembers(memberIDs, team)
@@ -593,11 +657,22 @@ func addTeamMembers(c *Context, w http.ResponseWriter, r *http.Request) {
membersWithErrors, err := c.App.AddTeamMembers(c.Params.TeamId, userIds, c.App.Session().UserId, graceful)
if membersWithErrors != nil {
errList := make([]string, 0, len(membersWithErrors))
for _, m := range membersWithErrors {
if m.Error != nil {
errList = append(errList, model.TeamMemberWithErrorToString(m))
}
}
auditRec.AddMeta("errors", errList)
}
if err != nil {
c.Err = err
return
}
auditRec.Success()
w.WriteHeader(http.StatusCreated)
if graceful {
@@ -615,6 +690,10 @@ func removeTeamMember(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
auditRec := c.MakeAuditRecord("removeTeamMember", audit.Fail)
defer c.LogAuditRec(auditRec)
auditRec.AddMeta("team_id", c.Params.TeamId)
if c.App.Session().UserId != c.Params.UserId {
if !c.App.SessionHasPermissionToTeam(*c.App.Session(), c.Params.TeamId, model.PERMISSION_REMOVE_USER_FROM_TEAM) {
c.SetPermissionError(model.PERMISSION_REMOVE_USER_FROM_TEAM)
@@ -627,12 +706,15 @@ func removeTeamMember(c *Context, w http.ResponseWriter, r *http.Request) {
c.Err = err
return
}
auditRec.AddMeta("team_name", team.Name)
auditRec.AddMeta("team_display", team.DisplayName)
user, err := c.App.GetUser(c.Params.UserId)
if err != nil {
c.Err = err
return
}
auditRec.AddMeta("remove_user_id", user.Id)
if team.IsGroupConstrained() && (c.Params.UserId != c.App.Session().UserId) && !user.IsBot {
c.Err = model.NewAppError("removeTeamMember", "api.team.remove_member.group_constrained.app_error", nil, "", http.StatusBadRequest)
@@ -644,6 +726,7 @@ func removeTeamMember(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
auditRec.Success()
ReturnStatusOK(w)
}
@@ -712,6 +795,11 @@ func updateTeamMemberRoles(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
auditRec := c.MakeAuditRecord("updateTeamMemberRoles", audit.Fail)
defer c.LogAuditRec(auditRec)
auditRec.AddMeta("team_id", c.Params.TeamId)
auditRec.AddMeta("update_user_id", c.Params.UserId)
if !c.App.SessionHasPermissionToTeam(*c.App.Session(), c.Params.TeamId, model.PERMISSION_MANAGE_TEAM_ROLES) {
c.SetPermissionError(model.PERMISSION_MANAGE_TEAM_ROLES)
return
@@ -722,6 +810,7 @@ func updateTeamMemberRoles(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
auditRec.Success()
ReturnStatusOK(w)
}
@@ -737,6 +826,14 @@ func updateTeamMemberSchemeRoles(c *Context, w http.ResponseWriter, r *http.Requ
return
}
auditRec := c.MakeAuditRecord("updateTeamMemberSchemeRoles", audit.Fail)
defer c.LogAuditRec(auditRec)
auditRec.AddMeta("team_id", c.Params.TeamId)
auditRec.AddMeta("update_user_id", c.Params.UserId)
auditRec.AddMeta("new_scheme_admin", schemeRoles.SchemeAdmin)
auditRec.AddMeta("new_scheme_user", schemeRoles.SchemeUser)
auditRec.AddMeta("new_scheme_guest", schemeRoles.SchemeGuest)
if !c.App.SessionHasPermissionToTeam(*c.App.Session(), c.Params.TeamId, model.PERMISSION_MANAGE_TEAM_ROLES) {
c.SetPermissionError(model.PERMISSION_MANAGE_TEAM_ROLES)
return
@@ -747,6 +844,7 @@ func updateTeamMemberSchemeRoles(c *Context, w http.ResponseWriter, r *http.Requ
return
}
auditRec.Success()
ReturnStatusOK(w)
}
@@ -925,6 +1023,10 @@ func importTeam(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
auditRec := c.MakeAuditRecord("importTeam", audit.Fail)
defer c.LogAuditRec(auditRec)
auditRec.AddMeta("team_id", c.Params.TeamId)
fileInfo := fileInfoArray[0]
fileData, err := fileInfo.Open()
@@ -933,6 +1035,9 @@ func importTeam(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
defer fileData.Close()
auditRec.AddMeta("filename", fileInfo.Filename)
auditRec.AddMeta("filesize", fileSize)
auditRec.AddMeta("from", importFrom)
var log *bytes.Buffer
switch importFrom {
@@ -949,6 +1054,7 @@ func importTeam(c *Context, w http.ResponseWriter, r *http.Request) {
if c.Err != nil {
w.WriteHeader(c.Err.StatusCode)
}
auditRec.Success()
w.Write([]byte(model.MapToJson(data)))
}
@@ -980,8 +1086,23 @@ func inviteUsersToTeam(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
auditRec := c.MakeAuditRecord("inviteUsersToTeam", audit.Fail)
defer c.LogAuditRec(auditRec)
auditRec.AddMeta("team_id", c.Params.TeamId)
auditRec.AddMeta("count", len(emailList))
auditRec.AddMeta("emails", emailList)
if graceful {
invitesWithError, err := c.App.InviteNewUsersToTeamGracefully(emailList, c.Params.TeamId, c.App.Session().UserId)
if invitesWithError != nil {
errList := make([]string, 0, len(invitesWithError))
for _, inv := range invitesWithError {
if inv.Error != nil {
errList = append(errList, model.EmailInviteWithErrorToString(inv))
}
}
auditRec.AddMeta("errors", errList)
}
if err != nil {
c.Err = err
return
@@ -996,6 +1117,7 @@ func inviteUsersToTeam(c *Context, w http.ResponseWriter, r *http.Request) {
}
ReturnStatusOK(w)
}
auditRec.Success()
}
func inviteGuestsToChannels(c *Context, w http.ResponseWriter, r *http.Request) {
@@ -1015,6 +1137,10 @@ func inviteGuestsToChannels(c *Context, w http.ResponseWriter, r *http.Request)
return
}
auditRec := c.MakeAuditRecord("inviteGuestsToChannels", audit.Fail)
defer c.LogAuditRec(auditRec)
auditRec.AddMeta("team_id", c.Params.TeamId)
if !c.App.SessionHasPermissionToTeam(*c.App.Session(), c.Params.TeamId, model.PERMISSION_INVITE_GUEST) {
c.SetPermissionError(model.PERMISSION_INVITE_GUEST)
return
@@ -1028,10 +1154,19 @@ func inviteGuestsToChannels(c *Context, w http.ResponseWriter, r *http.Request)
c.Err = err
return
}
auditRec.AddMeta("email_count", len(guestsInvite.Emails))
auditRec.AddMeta("emails", guestsInvite.Emails)
auditRec.AddMeta("channel_count", len(guestsInvite.Channels))
auditRec.AddMeta("channels", guestsInvite.Channels)
if graceful {
invitesWithError, err := c.App.InviteGuestsToChannelsGracefully(c.Params.TeamId, guestsInvite, c.App.Session().UserId)
if err != nil {
errList := make([]string, 0, len(invitesWithError))
for _, inv := range invitesWithError {
errList = append(errList, model.EmailInviteWithErrorToString(inv))
}
auditRec.AddMeta("errors", errList)
c.Err = err
return
}
@@ -1045,6 +1180,7 @@ func inviteGuestsToChannels(c *Context, w http.ResponseWriter, r *http.Request)
}
ReturnStatusOK(w)
}
auditRec.Success()
}
func getInviteInfo(c *Context, w http.ResponseWriter, r *http.Request) {
@@ -1078,11 +1214,15 @@ func invalidateAllEmailInvites(c *Context, w http.ResponseWriter, r *http.Reques
return
}
auditRec := c.MakeAuditRecord("invalidateAllEmailInvites", audit.Fail)
defer c.LogAuditRec(auditRec)
if err := c.App.InvalidateAllEmailInvites(); err != nil {
c.Err = err
return
}
auditRec.Success()
ReturnStatusOK(w)
}
@@ -1131,6 +1271,10 @@ func setTeamIcon(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
auditRec := c.MakeAuditRecord("setTeamIcon", audit.Fail)
defer c.LogAuditRec(auditRec)
auditRec.AddMeta("team_id", c.Params.TeamId)
if !c.App.SessionHasPermissionToTeam(*c.App.Session(), c.Params.TeamId, model.PERMISSION_MANAGE_TEAM) {
c.SetPermissionError(model.PERMISSION_MANAGE_TEAM)
return
@@ -1166,7 +1310,9 @@ func setTeamIcon(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
auditRec.Success()
c.LogAudit("")
ReturnStatusOK(w)
}
@@ -1176,6 +1322,10 @@ func removeTeamIcon(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
auditRec := c.MakeAuditRecord("removeTeamIcon", audit.Fail)
defer c.LogAuditRec(auditRec)
auditRec.AddMeta("team_id", c.Params.TeamId)
if !c.App.SessionHasPermissionToTeam(*c.App.Session(), c.Params.TeamId, model.PERMISSION_MANAGE_TEAM) {
c.SetPermissionError(model.PERMISSION_MANAGE_TEAM)
return
@@ -1186,7 +1336,9 @@ func removeTeamIcon(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
auditRec.Success()
c.LogAudit("")
ReturnStatusOK(w)
}
@@ -1202,6 +1354,10 @@ func updateTeamScheme(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
auditRec := c.MakeAuditRecord("updateTeamScheme", audit.Fail)
defer c.LogAuditRec(auditRec)
auditRec.AddMeta("team_id", c.Params.TeamId)
if c.App.License() == nil {
c.Err = model.NewAppError("Api4.UpdateTeamScheme", "api.team.update_team_scheme.license.error", nil, "", http.StatusNotImplemented)
return
@@ -1218,6 +1374,9 @@ func updateTeamScheme(c *Context, w http.ResponseWriter, r *http.Request) {
c.Err = err
return
}
auditRec.AddMeta("scheme_id", scheme.Id)
auditRec.AddMeta("scheme_name", scheme.Name)
auditRec.AddMeta("scheme_display", scheme.DisplayName)
if scheme.Scope != model.SCHEME_SCOPE_TEAM {
c.Err = model.NewAppError("Api4.UpdateTeamScheme", "api.team.update_team_scheme.scheme_scope.error", nil, "", http.StatusBadRequest)
@@ -1230,6 +1389,8 @@ func updateTeamScheme(c *Context, w http.ResponseWriter, r *http.Request) {
c.Err = err
return
}
auditRec.AddMeta("team_name", team.Name)
auditRec.AddMeta("team_display", team.DisplayName)
team.SchemeId = schemeID
@@ -1239,6 +1400,7 @@ func updateTeamScheme(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
auditRec.Success()
ReturnStatusOK(w)
}