1212publisher_pipeline.disable_host: true
1313{{ /contains }}
1414processors:
15+ - rename:
16+ fields:
17+ - from: json.error
18+ to: error
19+ ignore_missing: true
1520 - rename:
1621 fields:
1722 - from: json
@@ -191,7 +196,7 @@ processors:
191196 if (src[i] == null
192197 || (name=src[i].Name) == null
193198 || (newValue=src[i].NewValue) == null
194- || (oldValue=src[i].OldValue)) continue;
199+ || (oldValue=src[i].OldValue) == null ) continue;
195200 name = validFieldName(name);
196201 if (name in dict) {
197202 if (dict[name].NewValue instanceof Array) {
@@ -225,8 +230,113 @@ processors:
225230 return builder.Build();
226231 }
227232
228- function azureADLogonSchema(debug) {
233+ function typeMapEnrich(conversions) {
234+ return function (evt) {
235+ var action = evt.Get("event.action");
236+ if (action != null && conversions.hasOwnProperty(action)) {
237+ var conv = conversions[action];
238+ if (conv.action !== undefined) evt.Put("event.action", conv.action);
239+ if (conv.category !== undefined) evt.Put("event.category", conv.category);
240+ if (conv.type !== undefined) evt.Put("event.type", conv.type);
241+ var n = conv.copy !== undefined? conv.copy.length : 0;
242+ for (var i=0; i<n ; i++) {
243+ var value = evt.Get(conv.copy[i].from);
244+ if (value != null)
245+ evt.Put(conv.copy[i].to, value);
246+ }
247+ }
248+ }
249+ }
250+
251+ function azureADSchema(debug) {
252+ var azureADConversion = {
253+ ' Add user.' : {
254+ action: " added-user-account" ,
255+ category: ' iam' ,
256+ type: [' user' , ' creation' ],
257+ copy: [
258+ {
259+ from: ' o365audit.ObjectId' ,
260+ to: ' user.target.id' ,
261+ }
262+ ],
263+ },
264+ ' Update user.' : {
265+ action: " modified-user-account" ,
266+ category: ' iam' ,
267+ type: [' user' , ' change' ],
268+ copy: [
269+ {
270+ from: ' o365audit.ObjectId' ,
271+ to: ' user.target.id' ,
272+ }
273+ ],
274+ },
275+ ' Delete user.' : {
276+ action: " deleted-user-account" ,
277+ category: ' iam' ,
278+ type: [' user' , ' deletion' ],
279+ copy: [
280+ {
281+ from: ' o365audit.ObjectId' ,
282+ to: ' user.target.id' ,
283+ }
284+ ],
285+ },
286+ };
287+
229288 var builder = new PipelineBuilder(" o365.audit.AzureActiveDirectory" , debug);
289+ builder.Add(" setIAMFields" , typeMapEnrich(azureADConversion));
290+ return builder.Build();
291+ }
292+
293+ function teamsSchema(debug) {
294+ var teamsConversion = {
295+ ' TeamCreated' : {
296+ action: " added-group-account-to" ,
297+ category: ' iam' ,
298+ type: [' group' , ' creation' ],
299+ copy: [
300+ {
301+ from: ' o365audit.TeamName' ,
302+ to: ' group.name' ,
303+ }
304+ ],
305+ },
306+ ' MemberAdded' : {
307+ action: " added-users-to-group" ,
308+ category: ' iam' ,
309+ type: [' group' , ' change' ],
310+ },
311+
312+ ' Delete user.' : {
313+ action: " deleted-user-account" ,
314+ category: ' iam' ,
315+ type: [' user' , ' deletion' ],
316+ copy: [
317+ {
318+ from: ' o365audit.ObjectId' ,
319+ to: ' user.target.id' ,
320+ }
321+ ],
322+ },
323+ };
324+
325+ var builder = new PipelineBuilder(" o365.audit.MicrosoftTeams" , debug);
326+ builder.Add(" setIAMFields" , typeMapEnrich(teamsConversion));
327+ builder.Add(" groupMembersToRelatedUser" , function (evt) {
328+ var m = evt.Get(" o365audit.Members" );
329+ if (m = = null || m.forEach = = null) return;
330+ m.forEach(function (obj) {
331+ if (obj != null && obj.hasOwnProperty(' UPN' ))
332+ evt.AppendTo(' related.user' , obj.UPN);
333+ })
334+ })
335+ return builder.Build();
336+ }
337+
338+ function azureADLogonSchema(debug) {
339+ var builder = new PipelineBuilder(" o365.audit.AzureActiveDirectoryLogon" , debug);
230340 builder.Add(" setEventAuthFields" , function(evt){
231341 evt.Put(" event.category" , " authentication" );
232342 var outcome = evt.Get(" event.outcome" );
@@ -254,33 +364,34 @@ processors:
254364 ignore_missing: true,
255365 fail_on_error: false
256366 }));
257- builder.Add("setEventCategory", new processor.AddFields({
258- target: 'event',
259- fields: {
260- category: 'file',
261- },
262- }));
263- builder.Add("mapEventType", makeMapper({
264- from: 'o365audit.Operation',
265- to: 'event.type',
266- mappings: {
267- 'FileAccessed': 'access',
268- 'FileDeleted': 'deletion',
269- 'FileDownloaded': 'access',
270- 'FileModified': 'change',
271- 'FileMoved': 'change',
272- 'FileRenamed': 'change',
273- 'FileRestored': 'change',
274- 'FileUploaded': 'creation',
275- 'FolderCopied': 'creation',
276- 'FolderCreated': 'creation',
277- 'FolderDeleted': 'deletion',
278- 'FolderModified': 'change',
279- 'FolderMoved': 'change',
280- 'FolderRenamed': 'change',
281- 'FolderRestored': 'change',
282- },
283- }));
367+
368+ var actionToCategoryType = {
369+ ComplianceSettingChanged: [' configuration' , ' change' ],
370+ FileAccessed: [' file' , ' access' ],
371+ FileDeleted: [' file' , ' deletion' ],
372+ FileDownloaded: [' file' , ' access' ],
373+ FileModified: [' file' , ' change' ],
374+ FileMoved: [' file' , ' change' ],
375+ FileRenamed: [' file' , ' change' ],
376+ FileRestored: [' file' , ' change' ],
377+ FileUploaded: [' file' , ' creation' ],
378+ FolderCopied: [' file' , ' creation' ],
379+ FolderCreated: [' file' , ' creation' ],
380+ FolderDeleted: [' file' , ' deletion' ],
381+ FolderModified: [' file' , ' change' ],
382+ FolderMoved: [' file' , ' change' ],
383+ FolderRenamed: [' file' , ' change' ],
384+ FolderRestored: [' file' , ' change' ],
385+ };
386+
387+ builder.Add(" setEventFields" , function(evt) {
388+ var action = evt.Get(" o365audit.Operation" );
389+ if (action = = null) return;
390+ var fields = actionToCategoryType[action];
391+ if (fields = = null) return;
392+ evt.Put(" event.category" , fields[0]);
393+ evt.Put(" event.type" , fields[1]);
394+ });
284395 return builder.Build();
285396 }
286397
@@ -476,44 +587,94 @@ processors:
476587 fail_on_error: false
477588 }));
478589
479- var actionToCategoryType = {
480- // Network or verified admin changes the information that appears on
481- // member profiles for network users network.
482- ProcessProfileFields: [ "iam", "user"],
590+ var yammerConversion = {
591+ // Network or verified admin changes the Yammer network's configuration.
592+ // This includes setting the interval for exporting data and enabling chat.
593+ NetworkConfigurationUpdated: {
594+ category: "configuration",
595+ type: "change",
596+ },
483597 // Verified admin updates the Yammer network's security configuration.
484598 // This includes setting password expiration policies and restrictions
485599 // on IP addresses.
486- NetworkSecurityConfigurationUpdated: [ "iam", "admin"],
600+ NetworkSecurityConfigurationUpdated: {
601+ category: ["iam", "configuration"],
602+ type: ["admin", "change"],
603+ },
604+ // Verified admin updates the setting for the network data retention
605+ // policy to either Hard Delete or Soft Delete. Only verified admins
606+ // can perform this operation.
607+ SoftDeleteSettingsUpdated: {
608+ category: "configuration",
609+ type: "change",
610+ },
611+ // Network or verified admin changes the information that appears on
612+ // member profiles for network users network.
613+ ProcessProfileFields: {
614+ category: "configuration",
615+ type: "change"
616+ },
617+ // Verified admin turns Private Content Mode on or off. This mode
618+ // lets an admin view the posts in private groups and view private
619+ // messages between individual users (or groups of users). Only verified
620+ // admins only can perform this operation.
621+ SupervisorAdminToggled: {
622+ category: "configuration",
623+ type: "change"
624+ },
487625 // User uploads a file.
488- FileCreated: [ "file", "creation"],
626+ FileCreated: {
627+ category: "file",
628+ type: "creation"
629+ },
489630 // User creates a group.
490- GroupCreation: [ "iam", ["group", "creation"] ],
631+ GroupCreation: {
632+ category: "iam",
633+ type: ["group", "creation"],
634+ },
491635 // A group is deleted from Yammer.
492- GroupDeletion: [ "iam", ["group", "deletion"] ],
636+ GroupDeletion: {
637+ category: "iam",
638+ type: ["group", "deletion"]
639+ },
493640 // User downloads a file.
494- FileDownloaded: [ "file", "access"],
641+ FileDownloaded: {
642+ category: "file",
643+ type: "access"
644+ },
495645 // User shares a file with another user.
496- FileShared: [ "file", "access"],
646+ FileShared: {
647+ category: "file",
648+ type: "access"
649+ },
497650 // Network or verified admin suspends (deactivates) a user from Yammer.
498- NetworkUserSuspended: [ "iam", "user"],
651+ NetworkUserSuspended: {
652+ category: "iam",
653+ type: "user"
654+ },
499655 // User account is suspended (deactivated).
500- UserSuspension: [ "iam", "user"],
656+ UserSuspension: {
657+ category: "iam",
658+ type: "user"
659+ },
501660 // User changes the description of a file.
502- FileUpdateDescription: [ "file", "access"],
661+ FileUpdateDescription: {
662+ category: "file",
663+ type: "access"
664+ },
503665 // User changes the name of a file.
504- FileUpdateName: [ "file", "creation"],
666+ FileUpdateName: {
667+ category: "file",
668+ type: "creation",
669+ },
505670 // User views a file.
506- FileVisited: [ "file", "access"],
671+ FileVisited: {
672+ category: "file",
673+ type: "access",
674+ },
507675 };
508676
509- builder.Add("setEventFields", function(evt) {
510- var action = evt.Get("event.action");
511- if (action == null) return;
512- var fields = actionToCategoryType[action];
513- if (fields == null) return;
514- evt.Put("event.category", fields[0]);
515- evt.Put("event.type", fields[1]);
516- });
677+ builder.Add("setEventFields", typeMapEnrich(yammerConversion));
517678 return builder.Build();
518679 }
519680
@@ -598,6 +759,22 @@ processors:
598759 return builder.Build();
599760 }
600761
762+ function splitEmailUserID(prefix) {
763+ var idField = prefix + ".id",
764+ nameField = prefix + ".name",
765+ domainField = prefix + ".domain",
766+ emailField = prefix + ".email";
767+ return function(evt) {
768+ var email = evt.Get(idField);
769+ if (email == null) return;
770+ var pos = email.indexOf('@');
771+ if (pos === -1) return;
772+ evt.Put(emailField, email);
773+ evt.Put(nameField, email.substr(0, pos));
774+ evt.Put(domainField, email.substr(pos+1));
775+ }
776+ }
777+
601778 function AuditProcessor(tenant_names, debug) {
602779 var builder = new PipelineBuilder("o365.audit", debug);
603780
@@ -751,12 +928,14 @@ processors:
751928 },
752929 'ExchangeAdmin': exchangeAdminSchema(debug).Run,
753930 'ExchangeItem': exchangeMailboxSchema(debug).Run,
931+ 'AzureActiveDirectory': azureADSchema(debug).Run,
754932 'AzureActiveDirectoryStsLogon': azureADLogonSchema(debug).Run,
755933 'SharePointFileOperation': sharePointFileOperationSchema(debug).Run,
756934 'SecurityComplianceAlerts': securityComplianceAlertsSchema(debug).Run,
757935 'ComplianceDLPSharePoint': dlp.Run,
758936 'ComplianceDLPExchange': dlp.Run,
759937 'Yammer': yammerSchema(debug).Run,
938+ 'MicrosoftTeams': teamsSchema(debug).Run,
760939 }));
761940
762941 builder.Add("extractClientIPPortBrackets", new processor.Dissect({
@@ -807,12 +986,14 @@ processors:
807986 fail_on_error: false
808987 }));
809988
810- builder.Add("setUserFieldsFromId", new processor.Dissect({
811- tokenizer: "%{name}@%{domain}",
812- field: "user.id",
813- target_prefix: "user",
814- 'when.contains.user.id': '@',
815- }));
989+ [
990+ 'user',
991+ 'user.target',
992+ 'source.user',
993+ 'destination.user',
994+ ].forEach(function (prefix) {
995+ builder.Add('setFromID' + prefix, splitEmailUserID(prefix));
996+ })
816997
817998 builder.Add("setNetworkType", function(event) {
818999 var ip = event.Get("client.ip");
@@ -831,6 +1012,7 @@ processors:
8311012 builder.Add("setRelatedUser", appendFields({
8321013 fields: [
8331014 "user.name",
1015+ "user.target.name",
8341016 "file.owner",
8351017 ],
8361018 to: 'related.user'
@@ -896,4 +1078,4 @@ processors:
8961078 - add_fields:
8971079 target: ''
8981080 fields:
899- ecs.version: 1.6 .0
1081+ ecs.version: 1.8 .0
0 commit comments