diff --git a/filters/office365/o365.yml b/filters/office365/o365.yml index e638ee143..5f06c09bc 100755 --- a/filters/office365/o365.yml +++ b/filters/office365/o365.yml @@ -1,4 +1,4 @@ -# Microsoft 365 filter, version 1.2.3 +# Microsoft 365 filter, version 1.4.1 pipeline: - dataTypes: @@ -8,6 +8,45 @@ pipeline: source: raw - drop: where: oneOf("log.Operation", ['AINotesUpdate', 'AcceptedSharingLinkOnFolder', 'AccessRequestUpdated', 'AccessedOdataLink', 'AddCommentToIncident.', 'AddFormCoauthor', 'AddRemediatedData', 'AddTagsToIncident', 'AdminThreadMuted', 'AdminThreadUnmuted', 'AlertExcelDownloaded', 'AlertNotificationsRecipientAdded', 'AllowShareFormForCopy', 'AppPublishedToCatalog', 'AppUpdatedInCatalog', 'AppUpgraded', 'ApplyRecordLabel', 'ApproveDisposal', 'AssignUserToIncident', 'AuditSearchCancelled', 'AuditSearchCompleted', 'AuditSearchCreated', 'AuditSearchExportJobCompleted', 'AuditSearchExportJobCreated', 'AuditSearchExportResultsDownloaded', 'BackupItemAdded', 'BackupItemRemoved', 'BackupItemRestoreCompleted', 'BackupItemRestoreTriggered', 'BackupPolicyActivated', 'BackupPolicyPaused', 'BotAddedToTeam', 'BreakEnded', 'BurnJob', 'CanceledQuery', 'CaseUpdated', 'ChannelAdded', 'ChannelOwnerResponded', 'ChatRetrieved', 'ChatUpdated', 'ClassificationAdded', 'ClassificationDefinitionCreated', 'ClientViewSignaled', 'ClockedIn', 'ClockedOut', 'CloseConversation', 'CollectionCreated', 'CollectionHardDeleted', 'CollectionRenamed', 'CollectionSoftDeleted', 'CollectionUpdated', 'ComplianceManagerAutomationChange', 'ComplianceSettingChanged', 'ConnectToExcelWorkbook', 'ConnectorAdded', 'CopilotInteraction', 'Copy', 'Create', 'CreateComment', 'CreateCopilotPlugin', 'CreateCopilotPromptBook', 'CreateForm', 'CreateResponse', 'CreateTag', 'CreateUpdateRequest', 'CreateWorkingSet', 'CreateWorkingSetSearch', 'DataExport', 'DataShareCreated', 'DataShareDeleted', 'DeleteCopilotPlugin', 'DeleteCopilotPromptBook', 'DeleteSummaryLink', 'DeleteTag', 'DeleteWorkingSetSearch', 'DeletedResult', 'DisableCopilotPlugin', 'DisableCopilotPromptBook', 'DisallowShareFormForCopy', 'DocumentSensitivityMismatchDetected', 'DomainControllerCoverageExcelDownloaded', 'DownloadCopyOfLakeData', 'DownloadDocument', 'DownloadedReport', 'DraftRestoreTaskCreated', 'DraftRestoreTaskDeleted', 'DraftRestoreTaskEdited', 'EditUpdateRequest', 'EnableCopilotPlugin', 'EnableCopilotPromptBook', 'EntityCreated', 'ErrorRemediationJob', 'ExchangeDataProactivelyPreserved', 'ExecutedQuery', 'ExportForm', 'ExportJob', 'ExtendRetention', 'FailedValidation', 'FileCheckOutDiscarded', 'FileCheckedIn', 'FileCheckedOut', 'FileCopied', 'FileDeletedFirstStageRecycleBin', 'FileDeletedSecondStageRecycleBin', 'FileModifiedExtended', 'FileRecycled', 'FileRestored', 'FileSyncDownloadedFull', 'FileSyncUploadedFull', 'FileUpdateDescription', 'FileUploaded', 'FileVersionRecycled', 'FileVersionsAllMinorsRecycled', 'FileVersionsAllRecycled', 'FileVisited', 'FolderCopied', 'FolderCreated', 'FolderDeletedFirstStageRecycleBin', 'FolderDeletedSecondStageRecycleBin', 'FolderRecycled', 'FolderRestored', 'FolderSharingLinkShared', 'GenerateCopyOfLakeData', 'GetAllRestoreArtifactsInTask', 'GetBackupItem', 'GetRestoreTaskDetails', 'GetSummaryLink', 'GlossaryTermAssigned', 'GlossaryTermCreated', 'HoldRemoved', 'HoldUpdated', 'HubSiteJoined', 'HubSiteOrphanHubDeleted', 'HubSiteRegistered', 'InformationBarriersInsightsReportCompleted', 'InformationBarriersInsightsReportOneDriveSectionQueried', 'InformationBarriersInsightsReportSchedule', 'InformationBarriersInsightsReportSharePointSectionQueried', 'InviteSent', 'InviteeResponded', 'LabelContentExplorerAccessedItem', 'LegacyWorkflowEnabledSet', 'LinkedEntityCreated', 'ListAllBackupItemsInPolicies', 'ListAllBackupItemsInTenant', 'ListAllBackupItemsInWorkload', 'ListAllBackupPolicies', 'ListAllRestorePoints', 'ListAllRestoreTasks', 'ListColumnCreated', 'ListColumnUpdated', 'ListContentTypeCreated', 'ListContentTypeDeleted', 'ListContentTypeUpdated', 'ListCreated', 'ListForms', 'ListItemCreated', 'ListItemRecycled', 'ListItemRestored', 'LiveNotesUpdate', 'LockRecord', 'LogsCollection', 'ManagedSyncClientAllowed', 'MarkedMessageChanged', 'MeetingDetail', 'MeetingParticipantDetail', 'MessageCreatedHasLink', 'MessageCreatedNotification', 'MessageCreation', 'MessageDeleted', 'MessageDeletedNotification', 'MessageEditedHasLink', 'MessageHostedContentsListed', 'MessageRead', 'MessageUpdated', 'MessageUpdatedNotification', 'MonitoringAlertNotificationRecipientAdded', 'MonitoringAlertUpdated', 'MoveForm', 'MovedFormIntoCollection', 'MovedFormOutofCollection', 'NewAdaptiveScope', 'NewBackupPolicyCreated', 'NewComplianceTag', 'NewRetentionCompliancePolicy', 'NewsFeedEnabledSet', 'OffShiftDialogAccepted', 'OfficeOnDemandSet', 'OpenConversation', 'OpenShiftAdded', 'PagePrefetched', 'PageViewed', 'PageViewedExtended', 'PeopleResultsScopeSet', 'PerformedCardAction', 'PlanCopied', 'PlanListRead', 'PreviewForm', 'PreviewItemDownloaded', 'PreviewItemListed', 'PreviewModeEnabledSet', 'PreviewWorkingSetSearch', 'ProInvitation', 'ProjectCreated', 'ProjectListAccessed', 'PulseCancel', 'PulseCreate', 'PulseCreateDraft', 'PulseDeleteDraft', 'PulseExtendDeadline', 'PulseInvite', 'PulseShareResults', 'PulseSubmit', 'QuarantinePreview', 'QuarantineReleaseRequest', 'QuarantineReleaseRequestDeny', 'QuarantineViewHeader', 'RecordDelete', 'RelabelItem', 'RemediationActionAdded', 'RemediationActionUpdated', 'RemoveAdaptiveScope', 'RemoveComplianceTag', 'RemoveCuratedTopic', 'RemoveFormCoauthor', 'RemoveTagsFromIncident', 'RemovedSearchExported', 'RemovedSearchPreviewed', 'RemovedSearchResultsPurged', 'RemovedSearchResultsSentToZoom', 'ReportDownloaded', 'RequestAdded', 'RequestRespondedTo', 'RestoreTaskActivated', 'RestoreTaskCompleted', 'RoadmapAccessed', 'RoadmapCreated', 'RoadmapItemAccessed', 'RoadmapItemCreated', 'RunAntiVirusScan', 'ScheduleGroupAdded', 'ScheduleShared', 'SearchPermissionUpdated', 'SearchQueryPerformed', 'SearchRemoved', 'SearchReport', 'SearchReportRemoved', 'SearchResultsSentToZoom', 'SearchStopped', 'SearchUpdated', 'SearchViewed', 'Send', 'SensitivityLabelApplied', 'SensitivityLabelChanged', 'SensorActivationMethodConfigurationUpdated', 'SensorCreated', 'SensorDeploymentAccessKeyReceived', 'SensorDeploymentAccessKeyUpdated', 'SetAdvancedFeatures', 'SetRestrictiveRetentionUI', 'SharePointDataProactivelyPreserved', 'SharingInvitationRevoked', 'SharingInvitationUpdated', 'ShiftAdded', 'SiteAdminChangeRequest', 'SiteCollectionCreated', 'SiteCollectionQuotaModified', 'SiteColumnCreated', 'SiteColumnDeleted', 'SiteColumnUpdated', 'SiteContentTypeCreated', 'SiteContentTypeDeleted', 'SiteContentTypeUpdated', 'SoftDeleteSettingsUpdated', 'SubTaskCreated', 'SubmitResponse', 'SubmitUpdate', 'SubscribedToMessages', 'SupervisionRuleMatch', 'SupervisoryReviewTag', 'TabAdded', 'TabUpdated', 'TagFiles', 'TagJob', 'TaggingConfigurationUpdated', 'TaskAccessed', 'TaskAssigned', 'TaskCompleted', 'TaskCreated', 'TaskListCreated', 'TaskListRead', 'TaskRead', 'TeamCreated', 'ThreadAccessFailure', 'ThreadViewed', 'TimeClockEntryAdded', 'TimeOffAdded', 'UnlockRecord', 'Update', 'UpdateCopilotPlugin', 'UpdateCopilotPromptBook', 'UpdateCopilotSettings', 'UpdateIncidentStatus', 'UpdateResponse', 'UpdateTag', 'UpdateUsageReportsPrivacySetting', 'UpdateWorkingSetSearch', 'UpdatedPolicyConfigPriority', 'UploadedOrgData', 'UsagePolicyAcceptance', 'ViewBackupPolicyDetails', 'ViewDocument', 'ViewForm', 'ViewResponse', 'ViewResponses', 'ViewRuntimeForm', 'ViewUpdate', 'ViewedExplore', 'ViewedSearchExported', 'ViewedSearchPreviewed', 'WorkforceIntegrationAdded', 'WorkspaceCreated', 'updateddeviceconfiguration']) + # Capture documented Name/Value parameter identities before the legacy string + # cast loses their structure. The inbox rule and send-on-behalf flags mean a + # setting was supplied, including clearing it. The mailbox flag needs a non-empty + # forwarding address: Exchange records a cleared address as an empty value, and + # DeliverToMailboxAndForward alone sets no destination. No flag establishes an + # external recipient. Never trust markers supplied by the input record. + - delete: + fields: + - log.o365InboxForwardingChange + - log.o365MailboxForwardingSet + - log.o365SendOnBehalfChange + - add: + function: string + params: + key: log.o365InboxForwardingChange + value: "true" + where: >- + equals("log.Workload", "Exchange") && + oneOf("log.Operation", ["New-InboxRule", "Set-InboxRule"]) && + (exists("log.Parameters.#(Name==ForwardTo).Name") || + exists("log.Parameters.#(Name==ForwardAsAttachmentTo).Name") || + exists("log.Parameters.#(Name==RedirectTo).Name")) + - add: + function: string + params: + key: log.o365MailboxForwardingSet + value: "true" + where: >- + equals("log.Workload", "Exchange") && equals("log.Operation", "Set-Mailbox") && + (regexMatch("log.Parameters.#(Name==ForwardingAddress).Value", "(?s)^.+$") || + regexMatch("log.Parameters.#(Name==ForwardingSmtpAddress).Value", "(?s)^.+$")) + - add: + function: string + params: + key: log.o365SendOnBehalfChange + value: "true" + where: >- + equals("log.Workload", "Exchange") && equals("log.Operation", "Set-Mailbox") && + exists("log.Parameters.#(Name==GrantSendOnBehalfTo).Name") - cast: fields: - log.Parameters @@ -73,18 +112,125 @@ pipeline: from: - log.DestFolder.Path to: log.destFolderPath + # ResultStatus is workload-specific. Preserve it and derive only established + # operation outcomes; partial, pending and unknown results remain unset. + - delete: + fields: + - actionResult - add: function: string params: key: actionResult value: success - where: oneOf("log.ResultStatus", ["Succeeded", "Success", "Successful", "True"]) && !equals("action", "UserLoginFailed") + where: >- + !oneOf("log.RecordType", [1, 15, 41, 188, 189, 190, 191, 192, 193, 194, 231, 386, 387, 401, 402]) && + oneOf("log.ResultStatus", ["Succeeded", "Success", "Successful"]) && + !equals("action", "UserLoginFailed") + # ExchangeAdmin uses string True/False; these are not universal outcome codes. + - add: + function: string + params: + key: actionResult + value: success + where: equals("log.RecordType", 1) && equals("log.ResultStatus", "True") + # STS HTTP success and UserLoggedIn alone do not prove completed authentication. + # Require an explicit zero result code and reject contradictory/unknown errors. + # ErrorNumber is the corresponding field in observed STS audit records. + - add: + function: string + params: + key: actionResult + value: success + where: >- + equals("log.RecordType", 15) && + (equals("log.ErrorCode", 0) || equals("log.ErrorNumber", 0)) && + (!exists("log.ErrorCode") || equals("log.ErrorCode", 0)) && + (!exists("log.ErrorNumber") || equals("log.ErrorNumber", 0)) && + (!exists("log.LogonError") || regexMatch("log.LogonError", "^$")) && + (!exists("log.ResultStatus") || oneOf("log.ResultStatus", ["Succeeded", "Success", "Successful"])) && + !equals("action", "UserLoginFailed") + # Planner defines its own result enum. Audit records also emit its member names. + - add: + function: string + params: + key: actionResult + value: success + where: >- + oneOf("log.RecordType", [188, 189, 190, 191, 192, 193, 194, 231, 386, 387, 401, 402]) && + (equals("log.ResultStatus", 1) || equals("log.ResultStatus", "Success")) + # Safe Links reports the navigation decision separately from event processing. + # Values 4/5 mean the user overrode the page and navigated; 3 remains pending. + - add: + function: string + params: + key: actionResult + value: success + where: equals("log.RecordType", 41) && oneOf("log.URLClickAction", [4, 5]) + - add: + function: string + params: + key: actionResult + value: failure + where: >- + !oneOf("log.RecordType", [41, 188, 189, 190, 191, 192, 193, 194, 231, 386, 387, 401, 402]) && + (oneOf("log.ResultStatus", ["Failure", "Failed"]) || + (equals("log.RecordType", 1) && equals("log.ResultStatus", "False"))) - add: function: string params: key: actionResult - value: failed - where: oneOf("log.ResultStatus", ["Failure", "Failed"]) + value: failure + where: >- + equals("log.RecordType", 15) && + (greaterThan("log.ErrorCode", 0) || regexMatch("log.LogonError", "(?s)^.+$")) + - add: + function: string + params: + key: actionResult + value: failure + where: >- + oneOf("log.RecordType", [188, 189, 190, 191, 192, 193, 194, 231, 386, 387, 401, 402]) && + (equals("log.ResultStatus", 2) || equals("log.ResultStatus", "Failure")) + - add: + function: string + params: + key: actionResult + value: denied + where: >- + !oneOf("log.RecordType", [41, 188, 189, 190, 191, 192, 193, 194, 231, 386, 387, 401, 402]) && + equals("log.ResultStatus", "Blocked") + - add: + function: string + params: + key: actionResult + value: denied + where: >- + oneOf("log.RecordType", [188, 189, 190, 191, 192, 193, 194, 231, 386, 387, 401, 402]) && + (equals("log.ResultStatus", 3) || equals("log.ResultStatus", "AuthorizationFailure")) + # These exact operation names describe prevented user access, not successful + # administrative changes to a blocking policy. + - add: + function: string + params: + key: actionResult + value: denied + where: >- + oneOf("action", ["SharingInvitationBlocked", "UnmanagedSyncClientBlocked", "URLNavigationBlocked", "AccessRequestDenied"]) || + (equals("log.RecordType", 41) && equals("log.URLClickAction", 2)) + # KmsiInterrupt is the expected "Keep me signed in" prompt, not a final result. + - delete: + fields: + - actionResult + where: >- + equals("log.RecordType", 15) && + (equals("log.ErrorCode", 50140) || equals("log.ErrorNumber", 50140)) + # A failed login wins even when its HTTP request or audit operation succeeded. + - add: + function: string + params: + key: actionResult + value: failure + where: equals("action", "UserLoginFailed") - dynamic: plugin: com.utmstack.geolocation params: @@ -141,24 +287,23 @@ pipeline: - log.ItemName to: target.filename where: equals("log.Workload", "OneDrive") || equals("log.Workload", "SharePoint") - - add: - function: string - params: - key: actionResult - value: success - where: equals("log.ResultStatus", "PartiallySucceeded") - - add: - function: string - params: - key: actionResult - value: blocked - where: equals("log.ResultStatus", "Blocked") - - add: - function: string - params: - key: actionResult - value: failed - where: equals("action", "UserLoginFailed") + # Safe Links supplies the clicking user's IP and destination URL under its own + # documented fields. Copy them so vendor-specific queries retain the originals. + - grok: + source: log.UserIp + patterns: + - fieldName: origin.ip + pattern: (?s:.*) + where: >- + equals("log.RecordType", 41) && + (inCIDR("log.UserIp", "0.0.0.0/0") || inCIDR("log.UserIp", "::/0")) && + !inCIDR("log.UserIp", "0.0.0.0/32") && !inCIDR("log.UserIp", "::/128") + - grok: + source: log.URL + patterns: + - fieldName: target.url + pattern: (?s:.*) + where: equals("log.RecordType", 41) && regexMatch("log.URL", "(?s)^.+$") - delete: fields: - log.AppAccessContext diff --git a/plugins/alerts/o365_action_result_rules_test.go b/plugins/alerts/o365_action_result_rules_test.go new file mode 100644 index 000000000..78da5d1e7 --- /dev/null +++ b/plugins/alerts/o365_action_result_rules_test.go @@ -0,0 +1,348 @@ +package main + +// These tests use the pinned SDK CEL and history implementation. Raw normalization +// uses the explicit offline filter model in o365ActionResultNormalize, not a live +// EventProcessor. The history transport is a loopback mock, not customer storage. +import ( + "encoding/json" + "fmt" + "io" + "net/http" + "net/http/httptest" + "os" + "os/exec" + "reflect" + "strings" + "testing" + "time" + + sdkos "github.com/threatwinds/go-sdk/os" + "github.com/threatwinds/go-sdk/plugins" + "github.com/threatwinds/go-sdk/utils" + "github.com/tidwall/gjson" + "google.golang.org/protobuf/encoding/protojson" + "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/types/known/structpb" +) + +var o365OutcomeRuleFiles = []string{ + "possible_succesfull_password_guessing_o365", + "credential_access_microsoft_365_potential_password_spraying_attack", + "dlp_policy_violations", "safe_links_click_patterns", "insider_risk_indicators", "information_barriers_violations", +} + +func o365OutcomeRule(t *testing.T, name string) *plugins.Rule { + t.Helper() + b, err := utils.ReadPbYaml("../../rules/office365/" + name + ".yml") + if err != nil { + t.Fatal(err) + } + r := new(plugins.Rule) + if err = protojson.Unmarshal(b, r); err != nil { + t.Fatal(err) + } + r.Normalize() + return r +} + +func o365OutcomeRaw(t *testing.T, name string) string { + t.Helper() + event := map[string]any{"Workload": "Exchange", "ClientIP": "198.51.100.10", "UserId": "reviewer@example.test", "ResultStatus": "Blocked"} + switch name { + case "possible_succesfull_password_guessing_o365", "credential_access_microsoft_365_potential_password_spraying_attack": + event["Operation"] = "UserLoginFailed" + event["Workload"] = "AzureActiveDirectory" + event["RecordType"] = 15 + event["ResultStatus"] = "Succeeded" + case "dlp_policy_violations": + event["Operation"] = "DLPRuleMatch" + case "safe_links_click_patterns": + event["Operation"] = "ClickedSafeLink" + case "insider_risk_indicators": + event["Operation"] = "PolicyEvaluation" + event["PolicyName"] = "InsiderRiskPolicy" + case "information_barriers_violations": + event["Operation"] = "PolicyEvaluation" + event["PolicyType"] = "InformationBarrier" + default: + t.Fatal("unknown case", name) + } + b, err := json.Marshal(event) + if err != nil { + t.Fatal(err) + } + return string(b) +} + +func o365OutcomeSet(t *testing.T, event, path string, value any) string { + t.Helper() + var m map[string]any + if err := json.Unmarshal([]byte(event), &m); err != nil { + t.Fatal(err) + } + keys := strings.Split(path, ".") + node := m + for _, key := range keys[:len(keys)-1] { + next, ok := node[key].(map[string]any) + if !ok { + next = map[string]any{} + node[key] = next + } + node = next + } + key := keys[len(keys)-1] + if value == nil { + delete(node, key) + } else { + node[key] = value + } + b, err := json.Marshal(m) + if err != nil { + t.Fatal(err) + } + return string(b) +} + +func o365OutcomeAssert(t *testing.T, cache *plugins.CELCache, r *plugins.Rule, event string, want bool) { + t.Helper() + got, err := cache.Eval(r.Where, event) + if err != nil || got != want { + t.Fatalf("predicate got %v want %v: %v", got, want, err) + } +} + +func TestO365ActionResultRuleCompatibility(t *testing.T) { + cache := plugins.NewCELCache("o365-outcome-rules") + for _, name := range o365OutcomeRuleFiles { + t.Run(name, func(t *testing.T) { + r := o365OutcomeRule(t, name) + event := o365ActionResultNormalize(t, o365OutcomeRaw(t, name)) + o365OutcomeAssert(t, cache, r, event, true) + if gaps := fixtureHistoryPlaceholders(r.Correlation, event); len(gaps) != 0 { + t.Fatal(gaps) + } + failureRule := strings.Contains(name, "password_") + // Exercise extraction and normalization for a negative record as well + // as the positive raw fixture before testing legacy stored outcomes. + negativeRaw := o365OutcomeSet(t, o365OutcomeRaw(t, name), "ResultStatus", "Succeeded") + if failureRule { + negativeRaw = o365OutcomeSet(t, negativeRaw, "Operation", "UserLoggedIn") + negativeRaw = o365OutcomeSet(t, negativeRaw, "ErrorNumber", 0) + } + if name == "dlp_policy_violations" { + negativeRaw = o365OutcomeSet(t, negativeRaw, "ResultStatus", "Failed") + } + o365OutcomeAssert(t, cache, r, o365ActionResultNormalize(t, negativeRaw), false) + for _, outcome := range []string{"success", "failure", "failed", "denied", "blocked", "unknown", ""} { + want := outcome == "denied" || outcome == "blocked" + if failureRule { + want = outcome == "failure" || outcome == "failed" + } + if name == "dlp_policy_violations" { + want = outcome != "failure" && outcome != "failed" + } + t.Run(outcome, func(t *testing.T) { + o365OutcomeAssert(t, cache, r, o365OutcomeSet(t, event, "actionResult", outcome), want) + }) + } + // Preserve DLP's existing unknown-outcome detection scope; absence is not + // described as success. Other migrated outcome branches need an outcome. + o365OutcomeAssert(t, cache, r, o365OutcomeSet(t, event, "actionResult", nil), name == "dlp_policy_violations") + unrelated := o365OutcomeSet(t, event, "action", "UnrelatedOperation") + unrelated = o365OutcomeSet(t, unrelated, "log.PolicyName", nil) + unrelated = o365OutcomeSet(t, unrelated, "log.PolicyType", nil) + o365OutcomeAssert(t, cache, r, unrelated, false) + if failureRule || name == "safe_links_click_patterns" { + o365OutcomeAssert(t, cache, r, o365OutcomeSet(t, event, "origin.ip", nil), name == "safe_links_click_patterns") + } + if name == "possible_succesfull_password_guessing_o365" || name == "safe_links_click_patterns" { + o365OutcomeAssert(t, cache, r, o365OutcomeSet(t, event, "origin.user", nil), false) + } + }) + } +} + +func TestO365ActionResultPreservesIndependentBranches(t *testing.T) { + cache := plugins.NewCELCache("o365-independent-branches") + for _, tc := range []struct { + name, event string + want bool + }{ + {"insider_risk_indicators", `{"action":"InsiderRiskAlert","actionResult":"failure"}`, true}, + {"insider_risk_indicators", `{"log":{"RiskLevel":"High","AlertSource":"InsiderRiskManagement"}}`, true}, + {"insider_risk_indicators", `{"log":{"RiskLevel":"Low","AlertSource":"InsiderRiskManagement"}}`, false}, + {"information_barriers_violations", `{"action":"InformationBarrierPolicyViolation","origin":{"user":"reviewer@example.test"}}`, true}, + {"information_barriers_violations", `{"action":"CommunicationBlocked","log":{"ViolationType":"InformationBarrier"},"origin":{"user":"reviewer@example.test"}}`, true}, + {"information_barriers_violations", `{"action":"CommunicationBlocked","log":{"ViolationType":"Other"},"origin":{"user":"reviewer@example.test"}}`, false}, + } { + t.Run(tc.name+fmt.Sprint(tc.want), func(t *testing.T) { o365OutcomeAssert(t, cache, o365OutcomeRule(t, tc.name), tc.event, tc.want) }) + } +} + +func TestO365ActionResultSDKHistory(t *testing.T) { + // Isolate the SDK's process-global OpenSearch connection and field mapper. + if os.Getenv("UTM_O365_OUTCOME_HISTORY_CHILD") != "1" { + c := exec.Command(os.Args[0], "-test.run=^TestO365ActionResultSDKHistory$") + c.Env = append(os.Environ(), "UTM_O365_OUTCOME_HISTORY_CHILD=1") + if b, err := c.CombinedOutput(); err != nil { + t.Fatalf("isolated history: %v\n%s", err, b) + } + return + } + var history []string + var expectedTerms map[string]string + var window time.Duration + queries := 0 + mapping := map[string]any{"properties": map[string]any{ + "@timestamp": map[string]any{"type": "date"}, "action": map[string]any{"type": "keyword"}, + "origin": map[string]any{"properties": map[string]any{"user": map[string]any{"type": "keyword"}, "ip": map[string]any{"type": "ip"}}}, + "log": map[string]any{"properties": map[string]any{"PolicyType": map[string]any{"type": "keyword"}}}, + }} + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "application/json") + if strings.HasSuffix(r.URL.Path, "/_mapping") { + _ = json.NewEncoder(w).Encode(map[string]any{"v11-log-o365-test": map[string]any{"mappings": mapping}}) + return + } + if r.URL.Path != "/v11-log-o365-*/_search" { + t.Errorf("unexpected request %s", r.URL.Path) + http.Error(w, "bad request", 400) + return + } + queries++ + b, err := io.ReadAll(r.Body) + if err != nil { + t.Error(err) + return + } + q := string(b) + terms := map[string]string{} + cutoff := time.Time{} + clauses := append(gjson.Get(q, "query.bool.filter").Array(), gjson.Get(q, "query.bool.must").Array()...) + if gjson.Get(q, "query.bool.must_not").Exists() { + t.Error("unexpected negative history clauses") + } + for _, clause := range clauses { + if term := clause.Get("term"); term.Exists() { + for field, value := range term.Map() { + terms[strings.TrimSuffix(field, ".keyword")] = value.Get("value").String() + } + } else if span := clause.Get("range"); span.Exists() { + cutoff, err = time.Parse(time.RFC3339Nano, span.Get("@timestamp.gte").String()) + if err != nil { + t.Error(err) + } + } else { + t.Errorf("unsupported history clause %s", clause.Raw) + } + } + if !reflect.DeepEqual(terms, expectedTerms) { + t.Errorf("history scope got %v want %v", terms, expectedTerms) + } + if delta := time.Since(cutoff) - window; delta < -2*time.Second || delta > 2*time.Second { + t.Errorf("wrong cutoff %v", delta) + } + hits := []map[string]any{} + for _, doc := range history { + match := true + for field, value := range terms { + if gjson.Get(doc, field).String() != value { + match = false + } + } + stamp, err := time.Parse(time.RFC3339Nano, gjson.Get(doc, "@timestamp").String()) + if err != nil || stamp.Before(cutoff) { + match = false + } + if match { + hits = append(hits, map[string]any{"_id": fmt.Sprint(len(hits)), "_index": "v11-log-o365-test", "_source": map[string]any{}}) + } + } + _ = json.NewEncoder(w).Encode(map[string]any{"took": 1, "hits": map[string]any{"total": map[string]any{"value": len(hits), "relation": "eq"}, "hits": hits}}) + })) + defer server.Close() + if err := sdkos.Connect([]string{server.URL}, "", ""); err != nil { + t.Fatal(err) + } + cache := plugins.NewCELCache("o365-history") + for _, tc := range []struct { + name, within string + count uint64 + terms map[string]string + }{ + {"possible_succesfull_password_guessing_o365", "1m", 10, map[string]string{"action": "UserLoginFailed", "origin.user": "reviewer@example.test", "origin.ip": "198.51.100.10"}}, + {"credential_access_microsoft_365_potential_password_spraying_attack", "60s", 5, map[string]string{"origin.ip": "198.51.100.10"}}, + {"safe_links_click_patterns", "30m", 5, map[string]string{"origin.user": "reviewer@example.test", "action": "ClickedSafeLink"}}, + {"information_barriers_violations", "12h", 3, map[string]string{"origin.user": "reviewer@example.test", "log.PolicyType": "InformationBarrier"}}, + } { + t.Run(tc.name, func(t *testing.T) { + r := o365OutcomeRule(t, tc.name) + if len(r.Correlation) != 1 { + t.Fatal("unexpected history count") + } + search := r.Correlation[0] + if search.Count != tc.count || search.Within != tc.within { + t.Fatal("history threshold/window changed") + } + expectedTerms = tc.terms + window, _ = time.ParseDuration(tc.within) + event := o365ActionResultNormalize(t, o365OutcomeRaw(t, tc.name)) + o365OutcomeAssert(t, cache, r, event, true) + if tc.name == "possible_succesfull_password_guessing_o365" { + if gjson.Get(event, "log.clientIP").Exists() { + t.Fatal("test needs normalized IP without obsolete alias") + } + old := proto.Clone(search).(*plugins.SearchRequest) + for _, e := range old.With { + if e.Field == "origin.ip" { + e.Value = structpb.NewStringValue("{{.log.clientIP}}") + } + } + before := queries + if _, _, err := old.Execute(&event); err == nil { + t.Fatal("obsolete placeholder unexpectedly resolved") + } + if queries != before { + t.Fatal("unresolved placeholder issued query") + } + } + prior := o365OutcomeSet(t, event, "@timestamp", time.Now().Add(-window/2).UTC().Format(time.RFC3339Nano)) + history = nil + for i := uint64(0); i < tc.count-1; i++ { + history = append(history, prior) + } + if yes, _, err := search.Execute(&event); err != nil || yes { + t.Fatalf("below threshold: %v %v", yes, err) + } + history = append(history, prior) + if yes, _, err := search.Execute(&event); err != nil || !yes { + t.Fatalf("at threshold: %v %v", yes, err) + } + expired := o365OutcomeSet(t, prior, "@timestamp", time.Now().Add(-window-time.Minute).UTC().Format(time.RFC3339Nano)) + history[len(history)-1] = expired + if yes, _, err := search.Execute(&event); err != nil || yes { + t.Fatalf("expired history counted: %v %v", yes, err) + } + for field := range expectedTerms { + history[len(history)-1] = o365OutcomeSet(t, prior, field, "different-value") + if yes, _, err := search.Execute(&event); err != nil || yes { + t.Fatalf("different %s counted: %v %v", field, yes, err) + } + } + for _, expression := range search.With { + value := expression.Value.GetStringValue() + if strings.HasPrefix(value, "{{.") { + field := strings.TrimSuffix(strings.TrimPrefix(value, "{{."), "}}") + missing := o365OutcomeSet(t, event, field, nil) + before := queries + if _, _, err := search.Execute(&missing); err == nil { + t.Fatalf("missing %s accepted", field) + } + if queries != before { + t.Fatal("unresolved placeholder issued query") + } + } + } + }) + } +} diff --git a/plugins/alerts/o365_action_result_test.go b/plugins/alerts/o365_action_result_test.go new file mode 100644 index 000000000..bbc15d0fd --- /dev/null +++ b/plugins/alerts/o365_action_result_test.go @@ -0,0 +1,111 @@ +package main + +import ( + "encoding/json" + "os" + "path/filepath" + "reflect" + "testing" + + "github.com/threatwinds/go-sdk/plugins" + "github.com/threatwinds/go-sdk/utils" + "github.com/tidwall/gjson" + "google.golang.org/protobuf/encoding/protojson" +) + +// o365ActionResultNormalize runs fabricated raw JSON through the committed +// extraction/normalization model. Only external geolocation is omitted; it does +// not produce actionResult. This does not execute the closed EventProcessor, +// threat-intelligence membership, or alert creation. +func o365ActionResultNormalize(t *testing.T, raw string) string { + t.Helper() + b, err := utils.ReadPbYaml("../../filters/office365/o365.yml") + if err != nil { + t.Fatal(err) + } + cfg := new(plugins.Config) + if err = protojson.Unmarshal(b, cfg); err != nil { + t.Fatal(err) + } + for _, stage := range cfg.Pipeline { + steps := stage.Steps[:0] + for _, step := range stage.Steps { + if step.Dynamic != nil { + if step.Dynamic.Plugin != "com.utmstack.geolocation" { + t.Fatalf("unmodeled dynamic producer: %s", step.Dynamic.Plugin) + } + continue + } + steps = append(steps, step) + } + stage.Steps = steps + } + root := t.TempDir() + if err = os.Mkdir(filepath.Join(root, "filters"), 0700); err != nil { + t.Fatal(err) + } + b, err = protojson.Marshal(cfg) + if err != nil { + t.Fatal(err) + } + if err = os.WriteFile(filepath.Join(root, "filters", "o365.yml"), b, 0600); err != nil { + t.Fatal(err) + } + out, issues, err := normalize(root, Fixture{Filter: "o365.yml", Raw: &raw, DataType: "o365", DataSource: "synthetic-collector"}, plugins.NewCELCache("o365-raw-outcome")) + if err != nil || len(issues) != 0 { + t.Fatalf("raw extraction model: %v; CEL issues: %v", err, issues) + } + return out +} + +func TestO365ActionResult(t *testing.T) { + b, err := os.ReadFile("testdata/o365_action_result.json") + if err != nil { + t.Fatal(err) + } + var cases []struct { + Name string `json:"name"` + Raw string `json:"raw"` + Result string `json:"result"` + Preserve map[string]any `json:"preserve"` + Expected map[string]any `json:"expected"` + Absent []string `json:"absent"` + IP *bool `json:"ipEligible"` + } + if err = json.Unmarshal(b, &cases); err != nil || len(cases) == 0 { + t.Fatalf("cases: %v", err) + } + cache := plugins.NewCELCache("o365-result-predicates") + for _, tc := range cases { + t.Run(tc.Name, func(t *testing.T) { + out := o365ActionResultNormalize(t, tc.Raw) + got := gjson.Get(out, "actionResult") + if got.String() != tc.Result || (tc.Result == "" && got.Exists()) { + t.Fatalf("actionResult = %s, want %q", got.Raw, tc.Result) + } + for _, result := range []string{"success", "failure", "denied"} { + match, err := cache.Eval(`equals("actionResult","`+result+`") && inCIDR("origin.ip","0.0.0.0/0")`, out) + want := tc.Result == result && (tc.IP == nil || *tc.IP) + if err != nil || match != want { + t.Errorf("SDK %s-and-IP predicate = %v, %v", result, match, err) + } + } + for path, want := range tc.Preserve { + got := gjson.Get(out, path) + if !got.Exists() || !reflect.DeepEqual(got.Value(), want) { + t.Errorf("vendor field %s = %v, want %v", path, got.Value(), want) + } + } + for path, want := range tc.Expected { + if got := gjson.Get(out, path); !got.Exists() || !reflect.DeepEqual(got.Value(), want) { + t.Errorf("standard field %s = %v, want %v", path, got.Value(), want) + } + } + for _, path := range tc.Absent { + if gjson.Get(out, path).Exists() { + t.Errorf("unexpected field %s", path) + } + } + }) + } +} diff --git a/plugins/alerts/o365_awareness_test.go b/plugins/alerts/o365_awareness_test.go new file mode 100644 index 000000000..cdeae6736 --- /dev/null +++ b/plugins/alerts/o365_awareness_test.go @@ -0,0 +1,113 @@ +package main + +import ( + "encoding/json" + "os" + "reflect" + "strings" + "testing" + + "github.com/threatwinds/go-sdk/plugins" + "github.com/tidwall/gjson" +) + +// These fabricated raw records exercise the complete checked-in O365 filter +// model and the pinned SDK CEL. The EventProcessor playground separately runs +// the real parser; neither test claims customer alert indexing or notifications. +func TestO365AwarenessRawPredicatesAndGrouping(t *testing.T) { + var cases []struct { + Name string `json:"name"` + Raw string `json:"raw"` + Rule string `json:"rule"` + Match bool `json:"match"` + Expected map[string]any `json:"expected"` + Absent []string `json:"absent"` + } + b, err := os.ReadFile("testdata/o365_awareness.json") + if err != nil { + t.Fatal(err) + } + if err := json.Unmarshal(b, &cases); err != nil { + t.Fatal(err) + } + if len(cases) < 50 { + t.Fatalf("awareness fixture set unexpectedly small: %d", len(cases)) + } + paths := map[string]*plugins.Rule{} + for _, tc := range cases { + if _, ok := paths[tc.Rule]; ok { + continue + } + if !strings.HasPrefix(tc.Rule, "office365/") || !strings.HasSuffix(tc.Rule, ".yml") { + t.Fatalf("unexpected rule path %s", tc.Rule) + } + stem := strings.TrimSuffix(strings.TrimPrefix(tc.Rule, "office365/"), ".yml") + paths[tc.Rule] = o365OutcomeRule(t, stem) + } + if len(paths) != 8 { + t.Fatalf("want eight shipped awareness rules, got %d", len(paths)) + } + // One top-level alert per acting account and action; later changes become children, which the + // rule flood guard does not count. Grouping per object passed 50 top-level alerts a day. + want := []string{"lastEvent.tenantId", "lastEvent.log.OrganizationId", "dataSource", "adversary.user", "lastEvent.action"} + // Forwarding mail out of a mailbox is a common step after it is taken over, so the two + // forwarding rules alert at medium severity (highest impact value 2); the others stay low. + medium := map[string]bool{ + "office365/mail_forwarding_rules.yml": true, + "office365/mailbox_auto_forwarding_set_mailbox.yml": true, + } + for path, rule := range paths { + if !reflect.DeepEqual(rule.GroupBy, want) { + t.Fatalf("%s: grouping paths %v, want %v", path, rule.GroupBy, want) + } + if len(rule.DeduplicateBy) != 0 || len(rule.Correlation) != 0 || len(rule.AfterEvents) != 0 { + t.Fatalf("%s: awareness alerts should retain every change without history thresholds or suppression", path) + } + confidentiality := uint32(1) + if medium[path] { + confidentiality = 2 + } + if rule.Impact.GetConfidentiality() != confidentiality || rule.Impact.GetIntegrity() != 1 || rule.Impact.GetAvailability() != 0 || rule.Adversary != "origin" { + t.Fatalf("%s: invalid impact or attribution", path) + } + } + cache := plugins.NewCELCache("o365-awareness") + seen := map[string]bool{} + for _, tc := range cases { + t.Run(tc.Name, func(t *testing.T) { + if seen[tc.Name] { + t.Fatal("duplicate fixture") + } + seen[tc.Name] = true + event := o365ActionResultNormalize(t, tc.Raw) + for path, want := range tc.Expected { + got := gjson.Get(event, path) + if !got.Exists() || !reflect.DeepEqual(got.Value(), want) { + t.Errorf("normalized %s = %v, want %v", path, got.Value(), want) + } + } + for _, path := range tc.Absent { + if gjson.Get(event, path).Exists() { + t.Errorf("unexpected normalized %s", path) + } + } + matches := 0 + for path, rule := range paths { + got, err := cache.Eval(rule.Where, event) + if err != nil { + t.Fatalf("%s: CEL: %v", path, err) + } + want := path == tc.Rule && tc.Match + if got != want { + t.Errorf("%s: predicate = %v, want %v", path, got, want) + } + if got { + matches++ + } + } + if matches > 1 { + t.Errorf("one administrative change matched %d awareness rules", matches) + } + }) + } +} diff --git a/plugins/alerts/testdata/o365_action_result.json b/plugins/alerts/testdata/o365_action_result.json new file mode 100644 index 000000000..4fc43acdb --- /dev/null +++ b/plugins/alerts/testdata/o365_action_result.json @@ -0,0 +1,595 @@ +[ + { + "name": "completed-Success", + "raw": "{\"Operation\":\"FileDownloaded\",\"Workload\":\"SharePoint\",\"RecordType\":6,\"ClientIP\":\"192.0.2.10\",\"UserId\":\"analyst@example.invalid\",\"ResultStatus\":\"Success\"}", + "result": "success", + "preserve": { + "log.ResultStatus": "Success" + } + }, + { + "name": "completed-Succeeded", + "raw": "{\"Operation\":\"FileDownloaded\",\"Workload\":\"SharePoint\",\"RecordType\":6,\"ClientIP\":\"192.0.2.10\",\"UserId\":\"analyst@example.invalid\",\"ResultStatus\":\"Succeeded\"}", + "result": "success", + "preserve": { + "log.ResultStatus": "Succeeded" + } + }, + { + "name": "completed-Successful", + "raw": "{\"Operation\":\"FileDownloaded\",\"Workload\":\"SharePoint\",\"RecordType\":6,\"ClientIP\":\"192.0.2.10\",\"UserId\":\"analyst@example.invalid\",\"ResultStatus\":\"Successful\"}", + "result": "success", + "preserve": { + "log.ResultStatus": "Successful" + } + }, + { + "name": "failed-Failure", + "raw": "{\"Operation\":\"FileDownloaded\",\"Workload\":\"SharePoint\",\"RecordType\":6,\"ClientIP\":\"192.0.2.10\",\"UserId\":\"analyst@example.invalid\",\"ResultStatus\":\"Failure\"}", + "result": "failure", + "preserve": { + "log.ResultStatus": "Failure" + } + }, + { + "name": "failed-Failed", + "raw": "{\"Operation\":\"FileDownloaded\",\"Workload\":\"SharePoint\",\"RecordType\":6,\"ClientIP\":\"192.0.2.10\",\"UserId\":\"analyst@example.invalid\",\"ResultStatus\":\"Failed\"}", + "result": "failure", + "preserve": { + "log.ResultStatus": "Failed" + } + }, + { + "name": "blocked-status", + "raw": "{\"Operation\":\"FileDownloaded\",\"Workload\":\"SharePoint\",\"RecordType\":6,\"ClientIP\":\"192.0.2.10\",\"UserId\":\"analyst@example.invalid\",\"ResultStatus\":\"Blocked\"}", + "result": "denied", + "preserve": { + "log.ResultStatus": "Blocked" + } + }, + { + "name": "unresolved-PartiallySucceeded", + "raw": "{\"Operation\":\"FileDownloaded\",\"Workload\":\"SharePoint\",\"RecordType\":6,\"ClientIP\":\"192.0.2.10\",\"UserId\":\"analyst@example.invalid\",\"ResultStatus\":\"PartiallySucceeded\"}", + "result": "", + "preserve": { + "log.ResultStatus": "PartiallySucceeded" + } + }, + { + "name": "unresolved-Pending", + "raw": "{\"Operation\":\"FileDownloaded\",\"Workload\":\"SharePoint\",\"RecordType\":6,\"ClientIP\":\"192.0.2.10\",\"UserId\":\"analyst@example.invalid\",\"ResultStatus\":\"Pending\"}", + "result": "", + "preserve": { + "log.ResultStatus": "Pending" + } + }, + { + "name": "unresolved-InProgress", + "raw": "{\"Operation\":\"FileDownloaded\",\"Workload\":\"SharePoint\",\"RecordType\":6,\"ClientIP\":\"192.0.2.10\",\"UserId\":\"analyst@example.invalid\",\"ResultStatus\":\"InProgress\"}", + "result": "", + "preserve": { + "log.ResultStatus": "InProgress" + } + }, + { + "name": "unresolved-FutureVendorStatus", + "raw": "{\"Operation\":\"FileDownloaded\",\"Workload\":\"SharePoint\",\"RecordType\":6,\"ClientIP\":\"192.0.2.10\",\"UserId\":\"analyst@example.invalid\",\"ResultStatus\":\"FutureVendorStatus\"}", + "result": "", + "preserve": { + "log.ResultStatus": "FutureVendorStatus" + } + }, + { + "name": "unresolved-", + "raw": "{\"Operation\":\"FileDownloaded\",\"Workload\":\"SharePoint\",\"RecordType\":6,\"ClientIP\":\"192.0.2.10\",\"UserId\":\"analyst@example.invalid\",\"ResultStatus\":\"\"}", + "result": "", + "preserve": { + "log.ResultStatus": "" + } + }, + { + "name": "unresolved-None", + "raw": "{\"Operation\":\"FileDownloaded\",\"Workload\":\"SharePoint\",\"RecordType\":6,\"ClientIP\":\"192.0.2.10\",\"UserId\":\"analyst@example.invalid\",\"ResultStatus\":null}", + "result": "", + "preserve": { + "log.ResultStatus": null + } + }, + { + "name": "missing-outcome", + "raw": "{\"Operation\":\"FileDownloaded\",\"Workload\":\"SharePoint\",\"RecordType\":6,\"ClientIP\":\"192.0.2.10\",\"UserId\":\"analyst@example.invalid\"}", + "result": "", + "preserve": {} + }, + { + "name": "non-exchange-boolean-True", + "raw": "{\"Operation\":\"FileDownloaded\",\"Workload\":\"SharePoint\",\"RecordType\":6,\"ClientIP\":\"192.0.2.10\",\"UserId\":\"analyst@example.invalid\",\"ResultStatus\":\"True\"}", + "result": "", + "preserve": { + "log.ResultStatus": "True" + } + }, + { + "name": "non-exchange-boolean-False", + "raw": "{\"Operation\":\"FileDownloaded\",\"Workload\":\"SharePoint\",\"RecordType\":6,\"ClientIP\":\"192.0.2.10\",\"UserId\":\"analyst@example.invalid\",\"ResultStatus\":\"False\"}", + "result": "", + "preserve": { + "log.ResultStatus": "False" + } + }, + { + "name": "exchange-true", + "raw": "{\"Operation\":\"Set-Mailbox\",\"Workload\":\"Exchange\",\"RecordType\":1,\"ClientIP\":\"192.0.2.10\",\"UserId\":\"analyst@example.invalid\",\"ResultStatus\":\"True\"}", + "result": "success", + "preserve": { + "log.ResultStatus": "True" + } + }, + { + "name": "exchange-false", + "raw": "{\"Operation\":\"Set-Mailbox\",\"Workload\":\"Exchange\",\"RecordType\":1,\"ClientIP\":\"192.0.2.10\",\"UserId\":\"analyst@example.invalid\",\"ResultStatus\":\"False\"}", + "result": "failure", + "preserve": { + "log.ResultStatus": "False" + } + }, + { + "name": "failed-login-HTTP-success", + "raw": "{\"Operation\":\"UserLoginFailed\",\"Workload\":\"AzureActiveDirectory\",\"RecordType\":15,\"ClientIP\":\"192.0.2.10\",\"UserId\":\"analyst@example.invalid\",\"ResultStatus\":\"Success\",\"ErrorCode\":\"50126\",\"LogonError\":\"InvalidUserNameOrPassword\"}", + "result": "failure", + "preserve": { + "log.ResultStatus": "Success", + "log.ErrorCode": "50126", + "log.LogonError": "InvalidUserNameOrPassword" + } + }, + { + "name": "failed-login-contradictory-zero", + "raw": "{\"Operation\":\"UserLoginFailed\",\"Workload\":\"AzureActiveDirectory\",\"RecordType\":15,\"ClientIP\":\"192.0.2.10\",\"UserId\":\"analyst@example.invalid\",\"ResultStatus\":\"Success\",\"ErrorCode\":\"0\"}", + "result": "failure", + "preserve": { + "log.ResultStatus": "Success", + "log.ErrorCode": "0" + } + }, + { + "name": "sts-HTTP-only", + "raw": "{\"Operation\":\"PasswordLogonInitialAuthUsingPassword\",\"Workload\":\"AzureActiveDirectory\",\"RecordType\":15,\"ClientIP\":\"192.0.2.10\",\"UserId\":\"analyst@example.invalid\",\"ResultStatus\":\"Succeeded\"}", + "result": "", + "preserve": { + "log.ResultStatus": "Succeeded" + } + }, + { + "name": "sts-nonzero-error", + "raw": "{\"Operation\":\"PasswordLogonInitialAuthUsingPassword\",\"Workload\":\"AzureActiveDirectory\",\"RecordType\":15,\"ClientIP\":\"192.0.2.10\",\"UserId\":\"analyst@example.invalid\",\"ResultStatus\":\"Succeeded\",\"ErrorCode\":\"50076\"}", + "result": "failure", + "preserve": { + "log.ResultStatus": "Succeeded", + "log.ErrorCode": "50076" + } + }, + { + "name": "sts-logon-error", + "raw": "{\"Operation\":\"UserLoggedIn\",\"Workload\":\"AzureActiveDirectory\",\"RecordType\":15,\"ClientIP\":\"192.0.2.10\",\"UserId\":\"analyst@example.invalid\",\"ResultStatus\":\"Succeeded\",\"LogonError\":\"AuthenticationFailed\"}", + "result": "failure", + "preserve": { + "log.ResultStatus": "Succeeded", + "log.LogonError": "AuthenticationFailed" + } + }, + { + "name": "sts-success", + "raw": "{\"Operation\":\"UserLoggedIn\",\"Workload\":\"AzureActiveDirectory\",\"RecordType\":15,\"ClientIP\":\"192.0.2.10\",\"UserId\":\"analyst@example.invalid\",\"ResultStatus\":\"Success\",\"ErrorCode\":\"0\"}", + "result": "success", + "preserve": { + "log.ResultStatus": "Success", + "log.ErrorCode": "0" + } + }, + { + "name": "sts-zero-success", + "raw": "{\"Operation\":\"PasswordLogonInitialAuthUsingPassword\",\"Workload\":\"AzureActiveDirectory\",\"RecordType\":15,\"ClientIP\":\"192.0.2.10\",\"UserId\":\"analyst@example.invalid\",\"ResultStatus\":\"Succeeded\",\"ErrorCode\":\"0\"}", + "result": "success", + "preserve": { + "log.ResultStatus": "Succeeded", + "log.ErrorCode": "0" + } + }, + { + "name": "sts-unknown-error-code", + "raw": "{\"Operation\":\"UserLoggedIn\",\"Workload\":\"AzureActiveDirectory\",\"RecordType\":15,\"ClientIP\":\"192.0.2.10\",\"UserId\":\"analyst@example.invalid\",\"ResultStatus\":\"Success\",\"ErrorCode\":\"unrecognized\"}", + "result": "", + "preserve": { + "log.ResultStatus": "Success", + "log.ErrorCode": "unrecognized" + } + }, + { + "name": "sts-null-error-code", + "raw": "{\"Operation\":\"UserLoggedIn\",\"Workload\":\"AzureActiveDirectory\",\"RecordType\":15,\"ClientIP\":\"192.0.2.10\",\"UserId\":\"analyst@example.invalid\",\"ResultStatus\":\"Success\",\"ErrorCode\":null}", + "result": "", + "preserve": { + "log.ResultStatus": "Success", + "log.ErrorCode": null + } + }, + { + "name": "prevented-URLNavigationBlocked", + "raw": "{\"Operation\":\"URLNavigationBlocked\",\"Workload\":\"SharePoint\",\"RecordType\":6,\"ClientIP\":\"192.0.2.10\",\"UserId\":\"analyst@example.invalid\",\"ResultStatus\":\"Success\"}", + "result": "denied", + "preserve": { + "log.ResultStatus": "Success" + } + }, + { + "name": "prevented-SharingInvitationBlocked", + "raw": "{\"Operation\":\"SharingInvitationBlocked\",\"Workload\":\"SharePoint\",\"RecordType\":6,\"ClientIP\":\"192.0.2.10\",\"UserId\":\"analyst@example.invalid\",\"ResultStatus\":\"Success\"}", + "result": "denied", + "preserve": { + "log.ResultStatus": "Success" + } + }, + { + "name": "prevented-UnmanagedSyncClientBlocked", + "raw": "{\"Operation\":\"UnmanagedSyncClientBlocked\",\"Workload\":\"SharePoint\",\"RecordType\":6,\"ClientIP\":\"192.0.2.10\",\"UserId\":\"analyst@example.invalid\",\"ResultStatus\":\"Success\"}", + "result": "denied", + "preserve": { + "log.ResultStatus": "Success" + } + }, + { + "name": "prevented-AccessRequestDenied", + "raw": "{\"Operation\":\"AccessRequestDenied\",\"Workload\":\"SharePoint\",\"RecordType\":6,\"ClientIP\":\"192.0.2.10\",\"UserId\":\"analyst@example.invalid\",\"ResultStatus\":\"Success\"}", + "result": "denied", + "preserve": { + "log.ResultStatus": "Success" + } + }, + { + "name": "safe-links-2", + "raw": "{\"Operation\":\"ClickedSafeLink\",\"Workload\":\"ThreatIntelligence\",\"RecordType\":41,\"ClientIP\":\"192.0.2.10\",\"UserId\":\"analyst@example.invalid\",\"ResultStatus\":\"Success\",\"URLClickAction\":2}", + "result": "denied", + "preserve": { + "log.ResultStatus": "Success", + "log.URLClickAction": 2 + } + }, + { + "name": "safe-links-3", + "raw": "{\"Operation\":\"ClickedSafeLink\",\"Workload\":\"ThreatIntelligence\",\"RecordType\":41,\"ClientIP\":\"192.0.2.10\",\"UserId\":\"analyst@example.invalid\",\"ResultStatus\":\"Success\",\"URLClickAction\":3}", + "result": "", + "preserve": { + "log.ResultStatus": "Success", + "log.URLClickAction": 3 + } + }, + { + "name": "safe-links-4", + "raw": "{\"Operation\":\"ClickedSafeLink\",\"Workload\":\"ThreatIntelligence\",\"RecordType\":41,\"ClientIP\":\"192.0.2.10\",\"UserId\":\"analyst@example.invalid\",\"ResultStatus\":\"Success\",\"URLClickAction\":4}", + "result": "success", + "preserve": { + "log.ResultStatus": "Success", + "log.URLClickAction": 4 + } + }, + { + "name": "safe-links-5", + "raw": "{\"Operation\":\"ClickedSafeLink\",\"Workload\":\"ThreatIntelligence\",\"RecordType\":41,\"ClientIP\":\"192.0.2.10\",\"UserId\":\"analyst@example.invalid\",\"ResultStatus\":\"Success\",\"URLClickAction\":5}", + "result": "success", + "preserve": { + "log.ResultStatus": "Success", + "log.URLClickAction": 5 + } + }, + { + "name": "safe-links-999", + "raw": "{\"Operation\":\"ClickedSafeLink\",\"Workload\":\"ThreatIntelligence\",\"RecordType\":41,\"ClientIP\":\"192.0.2.10\",\"UserId\":\"analyst@example.invalid\",\"ResultStatus\":\"Success\",\"URLClickAction\":999}", + "result": "", + "preserve": { + "log.ResultStatus": "Success", + "log.URLClickAction": 999 + } + }, + { + "name": "safe-links-no-click-action", + "raw": "{\"Operation\":\"ClickedSafeLink\",\"Workload\":\"SharePoint\",\"RecordType\":41,\"ClientIP\":\"192.0.2.10\",\"UserId\":\"analyst@example.invalid\",\"ResultStatus\":\"Success\"}", + "result": "", + "preserve": { + "log.ResultStatus": "Success" + } + }, + { + "name": "planner-1", + "raw": "{\"Operation\":\"TaskModified\",\"Workload\":\"MicrosoftPlanner\",\"RecordType\":188,\"ClientIP\":\"192.0.2.10\",\"UserId\":\"analyst@example.invalid\",\"ResultStatus\":1}", + "result": "success", + "preserve": { + "log.ResultStatus": 1 + } + }, + { + "name": "planner-2", + "raw": "{\"Operation\":\"TaskModified\",\"Workload\":\"MicrosoftPlanner\",\"RecordType\":188,\"ClientIP\":\"192.0.2.10\",\"UserId\":\"analyst@example.invalid\",\"ResultStatus\":2}", + "result": "failure", + "preserve": { + "log.ResultStatus": 2 + } + }, + { + "name": "planner-3", + "raw": "{\"Operation\":\"TaskModified\",\"Workload\":\"MicrosoftPlanner\",\"RecordType\":188,\"ClientIP\":\"192.0.2.10\",\"UserId\":\"analyst@example.invalid\",\"ResultStatus\":3}", + "result": "denied", + "preserve": { + "log.ResultStatus": 3 + } + }, + { + "name": "planner-0", + "raw": "{\"Operation\":\"TaskModified\",\"Workload\":\"MicrosoftPlanner\",\"RecordType\":188,\"ClientIP\":\"192.0.2.10\",\"UserId\":\"analyst@example.invalid\",\"ResultStatus\":0}", + "result": "", + "preserve": { + "log.ResultStatus": 0 + } + }, + { + "name": "planner-4", + "raw": "{\"Operation\":\"TaskModified\",\"Workload\":\"MicrosoftPlanner\",\"RecordType\":188,\"ClientIP\":\"192.0.2.10\",\"UserId\":\"analyst@example.invalid\",\"ResultStatus\":4}", + "result": "", + "preserve": { + "log.ResultStatus": 4 + } + }, + { + "name": "non-planner-numeric-1", + "raw": "{\"Operation\":\"FileDownloaded\",\"Workload\":\"SharePoint\",\"RecordType\":6,\"ClientIP\":\"192.0.2.10\",\"UserId\":\"analyst@example.invalid\",\"ResultStatus\":1}", + "result": "", + "preserve": { + "log.ResultStatus": 1 + } + }, + { + "name": "non-planner-numeric-2", + "raw": "{\"Operation\":\"FileDownloaded\",\"Workload\":\"SharePoint\",\"RecordType\":6,\"ClientIP\":\"192.0.2.10\",\"UserId\":\"analyst@example.invalid\",\"ResultStatus\":2}", + "result": "", + "preserve": { + "log.ResultStatus": 2 + } + }, + { + "name": "non-planner-numeric-3", + "raw": "{\"Operation\":\"FileDownloaded\",\"Workload\":\"SharePoint\",\"RecordType\":6,\"ClientIP\":\"192.0.2.10\",\"UserId\":\"analyst@example.invalid\",\"ResultStatus\":3}", + "result": "", + "preserve": { + "log.ResultStatus": 3 + } + }, + { + "name": "sts-unresolved-Pending", + "raw": "{\"Operation\":\"UserLoggedIn\",\"Workload\":\"AzureActiveDirectory\",\"RecordType\":15,\"ClientIP\":\"192.0.2.10\",\"UserId\":\"analyst@example.invalid\",\"ResultStatus\":\"Pending\",\"ErrorCode\":\"0\"}", + "result": "", + "preserve": { + "log.ResultStatus": "Pending", + "log.ErrorCode": "0" + } + }, + { + "name": "sts-unresolved-InProgress", + "raw": "{\"Operation\":\"UserLoggedIn\",\"Workload\":\"AzureActiveDirectory\",\"RecordType\":15,\"ClientIP\":\"192.0.2.10\",\"UserId\":\"analyst@example.invalid\",\"ResultStatus\":\"InProgress\",\"ErrorCode\":\"0\"}", + "result": "", + "preserve": { + "log.ResultStatus": "InProgress", + "log.ErrorCode": "0" + } + }, + { + "name": "sts-unresolved-FutureOutcome", + "raw": "{\"Operation\":\"UserLoggedIn\",\"Workload\":\"AzureActiveDirectory\",\"RecordType\":15,\"ClientIP\":\"192.0.2.10\",\"UserId\":\"analyst@example.invalid\",\"ResultStatus\":\"FutureOutcome\",\"ErrorCode\":\"0\"}", + "result": "", + "preserve": { + "log.ResultStatus": "FutureOutcome", + "log.ErrorCode": "0" + } + }, + { + "name": "sts-unresolved-None", + "raw": "{\"Operation\":\"UserLoggedIn\",\"Workload\":\"AzureActiveDirectory\",\"RecordType\":15,\"ClientIP\":\"192.0.2.10\",\"UserId\":\"analyst@example.invalid\",\"ResultStatus\":null,\"ErrorCode\":\"0\"}", + "result": "", + "preserve": { + "log.ResultStatus": null, + "log.ErrorCode": "0" + } + }, + { + "name": "sts-observed-zero", + "raw": "{\"Operation\":\"UserLoggedIn\",\"Workload\":\"AzureActiveDirectory\",\"RecordType\":15,\"ClientIP\":\"192.0.2.10\",\"UserId\":\"analyst@example.invalid\",\"ResultStatus\":\"Success\",\"ErrorNumber\":\"0\"}", + "result": "success", + "preserve": { + "log.ErrorNumber": "0", + "log.ResultStatus": "Success" + } + }, + { + "name": "sts-observed-kmsi-interrupt", + "raw": "{\"Operation\":\"UserLoggedIn\",\"Workload\":\"AzureActiveDirectory\",\"RecordType\":15,\"ClientIP\":\"192.0.2.10\",\"UserId\":\"analyst@example.invalid\",\"ResultStatus\":\"Success\",\"ErrorNumber\":\"50140\",\"ExtendedProperties\":[{\"Name\":\"ResultStatusDetail\",\"Value\":\"Success\"},{\"Name\":\"RequestType\",\"Value\":\"Login:login\"}]}", + "result": "", + "preserve": { + "log.ErrorNumber": "50140", + "log.ExtendedProperties": [ + { + "Name": "ResultStatusDetail", + "Value": "Success" + }, + { + "Name": "RequestType", + "Value": "Login:login" + } + ], + "log.ResultStatus": "Success" + } + }, + { + "name": "sts-documented-kmsi-interrupt", + "raw": "{\"Operation\":\"UserLoggedIn\",\"Workload\":\"AzureActiveDirectory\",\"RecordType\":15,\"ClientIP\":\"192.0.2.10\",\"UserId\":\"analyst@example.invalid\",\"ResultStatus\":\"Success\",\"ErrorCode\":\"50140\"}", + "result": "", + "preserve": { + "log.ErrorCode": "50140", + "log.ResultStatus": "Success" + } + }, + { + "name": "sts-conflicting-code-aliases", + "raw": "{\"Operation\":\"UserLoggedIn\",\"Workload\":\"AzureActiveDirectory\",\"RecordType\":15,\"ClientIP\":\"192.0.2.10\",\"UserId\":\"analyst@example.invalid\",\"ResultStatus\":\"Success\",\"ErrorNumber\":\"50140\",\"ErrorCode\":\"0\"}", + "result": "", + "preserve": { + "log.ErrorNumber": "50140", + "log.ErrorCode": "0", + "log.ResultStatus": "Success" + } + }, + { + "name": "sts-unknown-error-number", + "raw": "{\"Operation\":\"UserLoggedIn\",\"Workload\":\"AzureActiveDirectory\",\"RecordType\":15,\"ClientIP\":\"192.0.2.10\",\"UserId\":\"analyst@example.invalid\",\"ResultStatus\":\"Success\",\"ErrorNumber\":\"new-code\"}", + "result": "", + "preserve": { + "log.ErrorNumber": "new-code", + "log.ResultStatus": "Success" + } + }, + { + "name": "sts-null-error-number", + "raw": "{\"Operation\":\"UserLoggedIn\",\"Workload\":\"AzureActiveDirectory\",\"RecordType\":15,\"ClientIP\":\"192.0.2.10\",\"UserId\":\"analyst@example.invalid\",\"ResultStatus\":\"Success\",\"ErrorNumber\":null}", + "result": "", + "preserve": { + "log.ErrorNumber": null, + "log.ResultStatus": "Success" + } + }, + { + "name": "sts-logon-error-with-zero-number", + "raw": "{\"Operation\":\"UserLoggedIn\",\"Workload\":\"AzureActiveDirectory\",\"RecordType\":15,\"ClientIP\":\"192.0.2.10\",\"UserId\":\"analyst@example.invalid\",\"ResultStatus\":\"Success\",\"ErrorNumber\":\"0\",\"LogonError\":\"FlowTokenExpired\"}", + "result": "failure", + "preserve": { + "log.ErrorNumber": "0", + "log.LogonError": "FlowTokenExpired", + "log.ResultStatus": "Success" + } + }, + { + "name": "sts-negative-unknown-code", + "raw": "{\"Operation\":\"UserLoggedIn\",\"Workload\":\"AzureActiveDirectory\",\"RecordType\":15,\"ClientIP\":\"192.0.2.10\",\"UserId\":\"analyst@example.invalid\",\"ResultStatus\":\"Success\",\"ErrorNumber\":\"999999\"}", + "result": "", + "preserve": { + "log.ErrorNumber": "999999", + "log.ResultStatus": "Success" + } + }, + { + "name": "planner-string-enum-Success", + "raw": "{\"Operation\":\"PlanRead\",\"Workload\":\"Planner\",\"RecordType\":188,\"ClientIP\":\"192.0.2.10\",\"UserId\":\"analyst@example.invalid\",\"ResultStatus\":\"Success\"}", + "result": "success", + "preserve": { + "log.ResultStatus": "Success" + } + }, + { + "name": "planner-string-enum-Failure", + "raw": "{\"Operation\":\"PlanRead\",\"Workload\":\"Planner\",\"RecordType\":188,\"ClientIP\":\"192.0.2.10\",\"UserId\":\"analyst@example.invalid\",\"ResultStatus\":\"Failure\"}", + "result": "failure", + "preserve": { + "log.ResultStatus": "Failure" + } + }, + { + "name": "planner-string-enum-AuthorizationFailure", + "raw": "{\"Operation\":\"PlanRead\",\"Workload\":\"Planner\",\"RecordType\":188,\"ClientIP\":\"192.0.2.10\",\"UserId\":\"analyst@example.invalid\",\"ResultStatus\":\"AuthorizationFailure\"}", + "result": "denied", + "preserve": { + "log.ResultStatus": "AuthorizationFailure" + } + }, + { + "name": "wrong-result-type-array", + "raw": "{\"Operation\":\"FileDownloaded\",\"Workload\":\"SharePoint\",\"RecordType\":6,\"ClientIP\":\"192.0.2.10\",\"UserId\":\"analyst@example.invalid\",\"ResultStatus\":[\"Success\"]}", + "result": "", + "preserve": { + "log.ResultStatus": [ + "Success" + ] + } + }, + { + "name": "wrong-result-type-object", + "raw": "{\"Operation\":\"FileDownloaded\",\"Workload\":\"SharePoint\",\"RecordType\":6,\"ClientIP\":\"192.0.2.10\",\"UserId\":\"analyst@example.invalid\",\"ResultStatus\":{\"value\":\"Success\"}}", + "result": "", + "preserve": { + "log.ResultStatus": { + "value": "Success" + } + } + }, + { + "name": "wrong-result-type-boolean", + "raw": "{\"Operation\":\"FileDownloaded\",\"Workload\":\"SharePoint\",\"RecordType\":6,\"ClientIP\":\"192.0.2.10\",\"UserId\":\"analyst@example.invalid\",\"ResultStatus\":true}", + "result": "", + "preserve": { + "log.ResultStatus": true + } + }, + { + "name": "safe-links-native-shape-allowed", + "raw": "{\"Operation\":\"ClickedSafeLink\",\"RecordType\":41,\"UserId\":\"analyst@example.invalid\",\"UserIp\":\"192.0.2.20\",\"URL\":\"https://example.invalid/path\",\"URLClickAction\":4,\"ResultStatus\":\"Success\"}", + "result": "success", + "preserve": { + "log.UserIp": "192.0.2.20", + "log.URL": "https://example.invalid/path", + "log.URLClickAction": 4 + }, + "expected": { + "target.url": "https://example.invalid/path", + "origin.ip": "192.0.2.20" + }, + "absent": [], + "ipEligible": true + }, + { + "name": "safe-links-native-shape-blocked", + "raw": "{\"Operation\":\"ClickedSafeLink\",\"RecordType\":41,\"UserId\":\"analyst@example.invalid\",\"UserIp\":\"192.0.2.20\",\"URL\":\"https://example.invalid/path\",\"URLClickAction\":2,\"ResultStatus\":\"Success\"}", + "result": "denied", + "preserve": { + "log.UserIp": "192.0.2.20", + "log.URL": "https://example.invalid/path", + "log.URLClickAction": 2 + }, + "expected": { + "target.url": "https://example.invalid/path", + "origin.ip": "192.0.2.20" + }, + "absent": [], + "ipEligible": true + }, + { + "name": "safe-links-native-shape-invalid-ip", + "raw": "{\"Operation\":\"ClickedSafeLink\",\"RecordType\":41,\"UserId\":\"analyst@example.invalid\",\"UserIp\":\"not-an-ip\",\"URL\":\"https://example.invalid/path\",\"URLClickAction\":4,\"ResultStatus\":\"Success\"}", + "result": "success", + "preserve": { + "log.UserIp": "not-an-ip", + "log.URL": "https://example.invalid/path", + "log.URLClickAction": 4 + }, + "expected": { + "target.url": "https://example.invalid/path" + }, + "absent": [ + "origin.ip" + ], + "ipEligible": false + }, + { + "name": "sts-login-label-without-final-code", + "raw": "{\"Operation\":\"UserLoggedIn\",\"Workload\":\"AzureActiveDirectory\",\"RecordType\":15,\"ClientIP\":\"192.0.2.10\",\"UserId\":\"analyst@example.invalid\",\"ResultStatus\":\"Success\"}", + "result": "", + "preserve": { + "log.ResultStatus": "Success" + } + } +] diff --git a/plugins/alerts/testdata/o365_awareness.json b/plugins/alerts/testdata/o365_awareness.json new file mode 100644 index 000000000..eaf9c57aa --- /dev/null +++ b/plugins/alerts/testdata/o365_awareness.json @@ -0,0 +1,3219 @@ +[ + { + "name": "inbox-New-InboxRule", + "raw": "{\"Operation\":\"New-InboxRule\",\"Workload\":\"Exchange\",\"RecordType\":1,\"ResultStatus\":\"True\",\"UserId\":\"administrator@example.invalid\",\"ObjectId\":\"mailbox@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\",\"Parameters\":[{\"Name\":\"Name\",\"Value\":\"Administrative rule\"}]}", + "rule": "office365/collection_microsoft_365_new_inbox_rule.yml", + "match": true, + "expected": { + "action": "New-InboxRule", + "log.Workload": "Exchange", + "log.RecordType": 1, + "origin.user": "administrator@example.invalid", + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "mailbox@example.invalid", + "log.ResultStatus": "True", + "actionResult": "success", + "log.Parameters": "[map[Name:Name Value:Administrative rule]]" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "target.user", + "log.o365InboxForwardingChange", + "log.o365MailboxForwardingSet", + "log.o365SendOnBehalfChange" + ] + }, + { + "name": "inbox-Set-InboxRule", + "raw": "{\"Operation\":\"Set-InboxRule\",\"Workload\":\"Exchange\",\"RecordType\":1,\"ResultStatus\":\"True\",\"UserId\":\"administrator@example.invalid\",\"ObjectId\":\"mailbox@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\",\"Parameters\":[{\"Name\":\"Name\",\"Value\":\"Administrative rule\"}]}", + "rule": "office365/collection_microsoft_365_new_inbox_rule.yml", + "match": true, + "expected": { + "action": "Set-InboxRule", + "log.Workload": "Exchange", + "log.RecordType": 1, + "origin.user": "administrator@example.invalid", + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "mailbox@example.invalid", + "log.ResultStatus": "True", + "actionResult": "success", + "log.Parameters": "[map[Name:Name Value:Administrative rule]]" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "target.user", + "log.o365InboxForwardingChange", + "log.o365MailboxForwardingSet", + "log.o365SendOnBehalfChange" + ] + }, + { + "name": "inbox-UpdateInboxRules-outlook-save", + "raw": "{\"Operation\":\"UpdateInboxRules\",\"Workload\":\"Exchange\",\"RecordType\":2,\"ResultStatus\":\"Succeeded\",\"UserId\":\"administrator@example.invalid\",\"ObjectId\":\"mailbox@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\",\"MailboxOwnerUPN\":\"mailbox@example.invalid\"}", + "rule": "office365/collection_microsoft_365_new_inbox_rule.yml", + "match": false, + "expected": { + "action": "UpdateInboxRules", + "log.Workload": "Exchange", + "log.RecordType": 2, + "origin.user": "administrator@example.invalid", + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "mailbox@example.invalid", + "target.user": "mailbox@example.invalid", + "log.ResultStatus": "Succeeded", + "actionResult": "success" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "log.MailboxOwnerUPN", + "log.Parameters", + "log.o365InboxForwardingChange", + "log.o365MailboxForwardingSet", + "log.o365SendOnBehalfChange" + ] + }, + { + "name": "inbox-Enable-InboxRule", + "raw": "{\"Operation\":\"Enable-InboxRule\",\"Workload\":\"Exchange\",\"RecordType\":1,\"ResultStatus\":\"True\",\"UserId\":\"administrator@example.invalid\",\"ObjectId\":\"mailbox@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\",\"Parameters\":[{\"Name\":\"Name\",\"Value\":\"Administrative rule\"}]}", + "rule": "office365/collection_microsoft_365_new_inbox_rule.yml", + "match": true, + "expected": { + "action": "Enable-InboxRule", + "log.Workload": "Exchange", + "log.RecordType": 1, + "origin.user": "administrator@example.invalid", + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "mailbox@example.invalid", + "log.ResultStatus": "True", + "actionResult": "success", + "log.Parameters": "[map[Name:Name Value:Administrative rule]]" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "target.user", + "log.o365InboxForwardingChange", + "log.o365MailboxForwardingSet", + "log.o365SendOnBehalfChange" + ] + }, + { + "name": "inbox-Disable-InboxRule", + "raw": "{\"Operation\":\"Disable-InboxRule\",\"Workload\":\"Exchange\",\"RecordType\":1,\"ResultStatus\":\"True\",\"UserId\":\"administrator@example.invalid\",\"ObjectId\":\"mailbox@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\",\"Parameters\":[{\"Name\":\"Name\",\"Value\":\"Administrative rule\"}]}", + "rule": "office365/collection_microsoft_365_new_inbox_rule.yml", + "match": true, + "expected": { + "action": "Disable-InboxRule", + "log.Workload": "Exchange", + "log.RecordType": 1, + "origin.user": "administrator@example.invalid", + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "mailbox@example.invalid", + "log.ResultStatus": "True", + "actionResult": "success", + "log.Parameters": "[map[Name:Name Value:Administrative rule]]" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "target.user", + "log.o365InboxForwardingChange", + "log.o365MailboxForwardingSet", + "log.o365SendOnBehalfChange" + ] + }, + { + "name": "inbox-Remove-InboxRule", + "raw": "{\"Operation\":\"Remove-InboxRule\",\"Workload\":\"Exchange\",\"RecordType\":1,\"ResultStatus\":\"True\",\"UserId\":\"administrator@example.invalid\",\"ObjectId\":\"mailbox@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\",\"Parameters\":[{\"Name\":\"Name\",\"Value\":\"Administrative rule\"}]}", + "rule": "office365/collection_microsoft_365_new_inbox_rule.yml", + "match": true, + "expected": { + "action": "Remove-InboxRule", + "log.Workload": "Exchange", + "log.RecordType": 1, + "origin.user": "administrator@example.invalid", + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "mailbox@example.invalid", + "log.ResultStatus": "True", + "actionResult": "success", + "log.Parameters": "[map[Name:Name Value:Administrative rule]]" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "target.user", + "log.o365InboxForwardingChange", + "log.o365MailboxForwardingSet", + "log.o365SendOnBehalfChange" + ] + }, + { + "name": "forward-New-InboxRule-ForwardTo", + "raw": "{\"Operation\":\"New-InboxRule\",\"Workload\":\"Exchange\",\"RecordType\":1,\"ResultStatus\":\"True\",\"UserId\":\"administrator@example.invalid\",\"ObjectId\":\"mailbox@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\",\"Parameters\":[{\"Name\":\"ForwardTo\",\"Value\":\"delegate@example.invalid\"}]}", + "rule": "office365/mail_forwarding_rules.yml", + "match": true, + "expected": { + "action": "New-InboxRule", + "log.Workload": "Exchange", + "log.RecordType": 1, + "origin.user": "administrator@example.invalid", + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "mailbox@example.invalid", + "log.ResultStatus": "True", + "actionResult": "success", + "log.Parameters": "[map[Name:ForwardTo Value:delegate@example.invalid]]", + "log.o365InboxForwardingChange": "true" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "target.user", + "log.o365MailboxForwardingSet", + "log.o365SendOnBehalfChange" + ] + }, + { + "name": "forward-clear-New-InboxRule-ForwardTo", + "raw": "{\"Operation\":\"New-InboxRule\",\"Workload\":\"Exchange\",\"RecordType\":1,\"ResultStatus\":\"True\",\"UserId\":\"administrator@example.invalid\",\"ObjectId\":\"mailbox@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\",\"Parameters\":[{\"Name\":\"ForwardTo\",\"Value\":\"\"}]}", + "rule": "office365/mail_forwarding_rules.yml", + "match": true, + "expected": { + "action": "New-InboxRule", + "log.Workload": "Exchange", + "log.RecordType": 1, + "origin.user": "administrator@example.invalid", + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "mailbox@example.invalid", + "log.ResultStatus": "True", + "actionResult": "success", + "log.Parameters": "[map[Name:ForwardTo Value:]]", + "log.o365InboxForwardingChange": "true" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "target.user", + "log.o365MailboxForwardingSet", + "log.o365SendOnBehalfChange" + ] + }, + { + "name": "forward-New-InboxRule-ForwardAsAttachmentTo", + "raw": "{\"Operation\":\"New-InboxRule\",\"Workload\":\"Exchange\",\"RecordType\":1,\"ResultStatus\":\"True\",\"UserId\":\"administrator@example.invalid\",\"ObjectId\":\"mailbox@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\",\"Parameters\":[{\"Name\":\"ForwardAsAttachmentTo\",\"Value\":\"delegate@example.invalid\"}]}", + "rule": "office365/mail_forwarding_rules.yml", + "match": true, + "expected": { + "action": "New-InboxRule", + "log.Workload": "Exchange", + "log.RecordType": 1, + "origin.user": "administrator@example.invalid", + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "mailbox@example.invalid", + "log.ResultStatus": "True", + "actionResult": "success", + "log.Parameters": "[map[Name:ForwardAsAttachmentTo Value:delegate@example.invalid]]", + "log.o365InboxForwardingChange": "true" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "target.user", + "log.o365MailboxForwardingSet", + "log.o365SendOnBehalfChange" + ] + }, + { + "name": "forward-clear-New-InboxRule-ForwardAsAttachmentTo", + "raw": "{\"Operation\":\"New-InboxRule\",\"Workload\":\"Exchange\",\"RecordType\":1,\"ResultStatus\":\"True\",\"UserId\":\"administrator@example.invalid\",\"ObjectId\":\"mailbox@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\",\"Parameters\":[{\"Name\":\"ForwardAsAttachmentTo\",\"Value\":\"\"}]}", + "rule": "office365/mail_forwarding_rules.yml", + "match": true, + "expected": { + "action": "New-InboxRule", + "log.Workload": "Exchange", + "log.RecordType": 1, + "origin.user": "administrator@example.invalid", + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "mailbox@example.invalid", + "log.ResultStatus": "True", + "actionResult": "success", + "log.Parameters": "[map[Name:ForwardAsAttachmentTo Value:]]", + "log.o365InboxForwardingChange": "true" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "target.user", + "log.o365MailboxForwardingSet", + "log.o365SendOnBehalfChange" + ] + }, + { + "name": "forward-New-InboxRule-RedirectTo", + "raw": "{\"Operation\":\"New-InboxRule\",\"Workload\":\"Exchange\",\"RecordType\":1,\"ResultStatus\":\"True\",\"UserId\":\"administrator@example.invalid\",\"ObjectId\":\"mailbox@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\",\"Parameters\":[{\"Name\":\"RedirectTo\",\"Value\":\"delegate@example.invalid\"}]}", + "rule": "office365/mail_forwarding_rules.yml", + "match": true, + "expected": { + "action": "New-InboxRule", + "log.Workload": "Exchange", + "log.RecordType": 1, + "origin.user": "administrator@example.invalid", + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "mailbox@example.invalid", + "log.ResultStatus": "True", + "actionResult": "success", + "log.Parameters": "[map[Name:RedirectTo Value:delegate@example.invalid]]", + "log.o365InboxForwardingChange": "true" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "target.user", + "log.o365MailboxForwardingSet", + "log.o365SendOnBehalfChange" + ] + }, + { + "name": "forward-clear-New-InboxRule-RedirectTo", + "raw": "{\"Operation\":\"New-InboxRule\",\"Workload\":\"Exchange\",\"RecordType\":1,\"ResultStatus\":\"True\",\"UserId\":\"administrator@example.invalid\",\"ObjectId\":\"mailbox@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\",\"Parameters\":[{\"Name\":\"RedirectTo\",\"Value\":\"\"}]}", + "rule": "office365/mail_forwarding_rules.yml", + "match": true, + "expected": { + "action": "New-InboxRule", + "log.Workload": "Exchange", + "log.RecordType": 1, + "origin.user": "administrator@example.invalid", + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "mailbox@example.invalid", + "log.ResultStatus": "True", + "actionResult": "success", + "log.Parameters": "[map[Name:RedirectTo Value:]]", + "log.o365InboxForwardingChange": "true" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "target.user", + "log.o365MailboxForwardingSet", + "log.o365SendOnBehalfChange" + ] + }, + { + "name": "forward-Set-InboxRule-ForwardTo", + "raw": "{\"Operation\":\"Set-InboxRule\",\"Workload\":\"Exchange\",\"RecordType\":1,\"ResultStatus\":\"True\",\"UserId\":\"administrator@example.invalid\",\"ObjectId\":\"mailbox@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\",\"Parameters\":[{\"Name\":\"ForwardTo\",\"Value\":\"delegate@example.invalid\"}]}", + "rule": "office365/mail_forwarding_rules.yml", + "match": true, + "expected": { + "action": "Set-InboxRule", + "log.Workload": "Exchange", + "log.RecordType": 1, + "origin.user": "administrator@example.invalid", + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "mailbox@example.invalid", + "log.ResultStatus": "True", + "actionResult": "success", + "log.Parameters": "[map[Name:ForwardTo Value:delegate@example.invalid]]", + "log.o365InboxForwardingChange": "true" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "target.user", + "log.o365MailboxForwardingSet", + "log.o365SendOnBehalfChange" + ] + }, + { + "name": "forward-clear-Set-InboxRule-ForwardTo", + "raw": "{\"Operation\":\"Set-InboxRule\",\"Workload\":\"Exchange\",\"RecordType\":1,\"ResultStatus\":\"True\",\"UserId\":\"administrator@example.invalid\",\"ObjectId\":\"mailbox@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\",\"Parameters\":[{\"Name\":\"ForwardTo\",\"Value\":\"\"}]}", + "rule": "office365/mail_forwarding_rules.yml", + "match": true, + "expected": { + "action": "Set-InboxRule", + "log.Workload": "Exchange", + "log.RecordType": 1, + "origin.user": "administrator@example.invalid", + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "mailbox@example.invalid", + "log.ResultStatus": "True", + "actionResult": "success", + "log.Parameters": "[map[Name:ForwardTo Value:]]", + "log.o365InboxForwardingChange": "true" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "target.user", + "log.o365MailboxForwardingSet", + "log.o365SendOnBehalfChange" + ] + }, + { + "name": "forward-Set-InboxRule-ForwardAsAttachmentTo", + "raw": "{\"Operation\":\"Set-InboxRule\",\"Workload\":\"Exchange\",\"RecordType\":1,\"ResultStatus\":\"True\",\"UserId\":\"administrator@example.invalid\",\"ObjectId\":\"mailbox@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\",\"Parameters\":[{\"Name\":\"ForwardAsAttachmentTo\",\"Value\":\"delegate@example.invalid\"}]}", + "rule": "office365/mail_forwarding_rules.yml", + "match": true, + "expected": { + "action": "Set-InboxRule", + "log.Workload": "Exchange", + "log.RecordType": 1, + "origin.user": "administrator@example.invalid", + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "mailbox@example.invalid", + "log.ResultStatus": "True", + "actionResult": "success", + "log.Parameters": "[map[Name:ForwardAsAttachmentTo Value:delegate@example.invalid]]", + "log.o365InboxForwardingChange": "true" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "target.user", + "log.o365MailboxForwardingSet", + "log.o365SendOnBehalfChange" + ] + }, + { + "name": "forward-clear-Set-InboxRule-ForwardAsAttachmentTo", + "raw": "{\"Operation\":\"Set-InboxRule\",\"Workload\":\"Exchange\",\"RecordType\":1,\"ResultStatus\":\"True\",\"UserId\":\"administrator@example.invalid\",\"ObjectId\":\"mailbox@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\",\"Parameters\":[{\"Name\":\"ForwardAsAttachmentTo\",\"Value\":\"\"}]}", + "rule": "office365/mail_forwarding_rules.yml", + "match": true, + "expected": { + "action": "Set-InboxRule", + "log.Workload": "Exchange", + "log.RecordType": 1, + "origin.user": "administrator@example.invalid", + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "mailbox@example.invalid", + "log.ResultStatus": "True", + "actionResult": "success", + "log.Parameters": "[map[Name:ForwardAsAttachmentTo Value:]]", + "log.o365InboxForwardingChange": "true" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "target.user", + "log.o365MailboxForwardingSet", + "log.o365SendOnBehalfChange" + ] + }, + { + "name": "forward-Set-InboxRule-RedirectTo", + "raw": "{\"Operation\":\"Set-InboxRule\",\"Workload\":\"Exchange\",\"RecordType\":1,\"ResultStatus\":\"True\",\"UserId\":\"administrator@example.invalid\",\"ObjectId\":\"mailbox@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\",\"Parameters\":[{\"Name\":\"RedirectTo\",\"Value\":\"delegate@example.invalid\"}]}", + "rule": "office365/mail_forwarding_rules.yml", + "match": true, + "expected": { + "action": "Set-InboxRule", + "log.Workload": "Exchange", + "log.RecordType": 1, + "origin.user": "administrator@example.invalid", + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "mailbox@example.invalid", + "log.ResultStatus": "True", + "actionResult": "success", + "log.Parameters": "[map[Name:RedirectTo Value:delegate@example.invalid]]", + "log.o365InboxForwardingChange": "true" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "target.user", + "log.o365MailboxForwardingSet", + "log.o365SendOnBehalfChange" + ] + }, + { + "name": "forward-clear-Set-InboxRule-RedirectTo", + "raw": "{\"Operation\":\"Set-InboxRule\",\"Workload\":\"Exchange\",\"RecordType\":1,\"ResultStatus\":\"True\",\"UserId\":\"administrator@example.invalid\",\"ObjectId\":\"mailbox@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\",\"Parameters\":[{\"Name\":\"RedirectTo\",\"Value\":\"\"}]}", + "rule": "office365/mail_forwarding_rules.yml", + "match": true, + "expected": { + "action": "Set-InboxRule", + "log.Workload": "Exchange", + "log.RecordType": 1, + "origin.user": "administrator@example.invalid", + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "mailbox@example.invalid", + "log.ResultStatus": "True", + "actionResult": "success", + "log.Parameters": "[map[Name:RedirectTo Value:]]", + "log.o365InboxForwardingChange": "true" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "target.user", + "log.o365MailboxForwardingSet", + "log.o365SendOnBehalfChange" + ] + }, + { + "name": "mailbox-forward-ForwardingAddress", + "raw": "{\"Operation\":\"Set-Mailbox\",\"Workload\":\"Exchange\",\"RecordType\":1,\"ResultStatus\":\"True\",\"UserId\":\"administrator@example.invalid\",\"ObjectId\":\"mailbox@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\",\"Parameters\":[{\"Name\":\"ForwardingAddress\",\"Value\":\"recipient@example.invalid\"}]}", + "rule": "office365/mailbox_auto_forwarding_set_mailbox.yml", + "match": true, + "expected": { + "action": "Set-Mailbox", + "log.Workload": "Exchange", + "log.RecordType": 1, + "origin.user": "administrator@example.invalid", + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "mailbox@example.invalid", + "log.ResultStatus": "True", + "actionResult": "success", + "log.Parameters": "[map[Name:ForwardingAddress Value:recipient@example.invalid]]", + "log.o365MailboxForwardingSet": "true" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "target.user", + "log.o365InboxForwardingChange", + "log.o365SendOnBehalfChange" + ] + }, + { + "name": "mailbox-forward-clear-ForwardingAddress", + "raw": "{\"Operation\":\"Set-Mailbox\",\"Workload\":\"Exchange\",\"RecordType\":1,\"ResultStatus\":\"True\",\"UserId\":\"administrator@example.invalid\",\"ObjectId\":\"mailbox@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\",\"Parameters\":[{\"Name\":\"ForwardingAddress\",\"Value\":\"\"}]}", + "rule": "office365/mailbox_auto_forwarding_set_mailbox.yml", + "match": false, + "expected": { + "action": "Set-Mailbox", + "log.Workload": "Exchange", + "log.RecordType": 1, + "origin.user": "administrator@example.invalid", + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "mailbox@example.invalid", + "log.ResultStatus": "True", + "actionResult": "success", + "log.Parameters": "[map[Name:ForwardingAddress Value:]]" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "target.user", + "log.o365InboxForwardingChange", + "log.o365SendOnBehalfChange", + "log.o365MailboxForwardingSet" + ] + }, + { + "name": "mailbox-forward-ForwardingSmtpAddress", + "raw": "{\"Operation\":\"Set-Mailbox\",\"Workload\":\"Exchange\",\"RecordType\":1,\"ResultStatus\":\"True\",\"UserId\":\"administrator@example.invalid\",\"ObjectId\":\"mailbox@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\",\"Parameters\":[{\"Name\":\"ForwardingSmtpAddress\",\"Value\":\"recipient@example.invalid\"}]}", + "rule": "office365/mailbox_auto_forwarding_set_mailbox.yml", + "match": true, + "expected": { + "action": "Set-Mailbox", + "log.Workload": "Exchange", + "log.RecordType": 1, + "origin.user": "administrator@example.invalid", + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "mailbox@example.invalid", + "log.ResultStatus": "True", + "actionResult": "success", + "log.Parameters": "[map[Name:ForwardingSmtpAddress Value:recipient@example.invalid]]", + "log.o365MailboxForwardingSet": "true" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "target.user", + "log.o365InboxForwardingChange", + "log.o365SendOnBehalfChange" + ] + }, + { + "name": "mailbox-forward-clear-ForwardingSmtpAddress", + "raw": "{\"Operation\":\"Set-Mailbox\",\"Workload\":\"Exchange\",\"RecordType\":1,\"ResultStatus\":\"True\",\"UserId\":\"administrator@example.invalid\",\"ObjectId\":\"mailbox@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\",\"Parameters\":[{\"Name\":\"ForwardingSmtpAddress\",\"Value\":\"\"}]}", + "rule": "office365/mailbox_auto_forwarding_set_mailbox.yml", + "match": false, + "expected": { + "action": "Set-Mailbox", + "log.Workload": "Exchange", + "log.RecordType": 1, + "origin.user": "administrator@example.invalid", + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "mailbox@example.invalid", + "log.ResultStatus": "True", + "actionResult": "success", + "log.Parameters": "[map[Name:ForwardingSmtpAddress Value:]]" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "target.user", + "log.o365InboxForwardingChange", + "log.o365SendOnBehalfChange", + "log.o365MailboxForwardingSet" + ] + }, + { + "name": "mailbox-forward-DeliverToMailboxAndForward", + "raw": "{\"Operation\":\"Set-Mailbox\",\"Workload\":\"Exchange\",\"RecordType\":1,\"ResultStatus\":\"True\",\"UserId\":\"administrator@example.invalid\",\"ObjectId\":\"mailbox@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\",\"Parameters\":[{\"Name\":\"DeliverToMailboxAndForward\",\"Value\":\"True\"}]}", + "rule": "office365/mailbox_auto_forwarding_set_mailbox.yml", + "match": false, + "expected": { + "action": "Set-Mailbox", + "log.Workload": "Exchange", + "log.RecordType": 1, + "origin.user": "administrator@example.invalid", + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "mailbox@example.invalid", + "log.ResultStatus": "True", + "actionResult": "success", + "log.Parameters": "[map[Name:DeliverToMailboxAndForward Value:True]]" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "target.user", + "log.o365InboxForwardingChange", + "log.o365SendOnBehalfChange", + "log.o365MailboxForwardingSet" + ] + }, + { + "name": "mailbox-forward-clear-DeliverToMailboxAndForward", + "raw": "{\"Operation\":\"Set-Mailbox\",\"Workload\":\"Exchange\",\"RecordType\":1,\"ResultStatus\":\"True\",\"UserId\":\"administrator@example.invalid\",\"ObjectId\":\"mailbox@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\",\"Parameters\":[{\"Name\":\"DeliverToMailboxAndForward\",\"Value\":\"False\"}]}", + "rule": "office365/mailbox_auto_forwarding_set_mailbox.yml", + "match": false, + "expected": { + "action": "Set-Mailbox", + "log.Workload": "Exchange", + "log.RecordType": 1, + "origin.user": "administrator@example.invalid", + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "mailbox@example.invalid", + "log.ResultStatus": "True", + "actionResult": "success", + "log.Parameters": "[map[Name:DeliverToMailboxAndForward Value:False]]" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "target.user", + "log.o365InboxForwardingChange", + "log.o365SendOnBehalfChange", + "log.o365MailboxForwardingSet" + ] + }, + { + "name": "mailbox-forward-ForwardingAddress-with-cleared-smtp", + "raw": "{\"Operation\":\"Set-Mailbox\",\"Workload\":\"Exchange\",\"RecordType\":1,\"ResultStatus\":\"True\",\"UserId\":\"administrator@example.invalid\",\"ObjectId\":\"mailbox@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\",\"Parameters\":[{\"Name\":\"ForwardingSmtpAddress\",\"Value\":\"\"},{\"Name\":\"ForwardingAddress\",\"Value\":\"recipient@example.invalid\"},{\"Name\":\"DeliverToMailboxAndForward\",\"Value\":\"False\"}]}", + "rule": "office365/mailbox_auto_forwarding_set_mailbox.yml", + "match": true, + "expected": { + "action": "Set-Mailbox", + "log.Workload": "Exchange", + "log.RecordType": 1, + "origin.user": "administrator@example.invalid", + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "mailbox@example.invalid", + "log.ResultStatus": "True", + "actionResult": "success", + "log.o365MailboxForwardingSet": "true" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "target.user", + "log.o365InboxForwardingChange", + "log.o365SendOnBehalfChange" + ] + }, + { + "name": "mailbox-forward-ForwardingSmtpAddress-without-copy", + "raw": "{\"Operation\":\"Set-Mailbox\",\"Workload\":\"Exchange\",\"RecordType\":1,\"ResultStatus\":\"True\",\"UserId\":\"administrator@example.invalid\",\"ObjectId\":\"mailbox@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\",\"Parameters\":[{\"Name\":\"ForwardingSmtpAddress\",\"Value\":\"smtp:recipient@example.invalid\"},{\"Name\":\"DeliverToMailboxAndForward\",\"Value\":\"False\"}]}", + "rule": "office365/mailbox_auto_forwarding_set_mailbox.yml", + "match": true, + "expected": { + "action": "Set-Mailbox", + "log.Workload": "Exchange", + "log.RecordType": 1, + "origin.user": "administrator@example.invalid", + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "mailbox@example.invalid", + "log.ResultStatus": "True", + "actionResult": "success", + "log.o365MailboxForwardingSet": "true" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "target.user", + "log.o365InboxForwardingChange", + "log.o365SendOnBehalfChange" + ] + }, + { + "name": "mailbox-forward-clear-all", + "raw": "{\"Operation\":\"Set-Mailbox\",\"Workload\":\"Exchange\",\"RecordType\":1,\"ResultStatus\":\"True\",\"UserId\":\"administrator@example.invalid\",\"ObjectId\":\"mailbox@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\",\"Parameters\":[{\"Name\":\"ForwardingSmtpAddress\",\"Value\":\"\"},{\"Name\":\"ForwardingAddress\",\"Value\":\"\"},{\"Name\":\"DeliverToMailboxAndForward\",\"Value\":\"False\"}]}", + "rule": "office365/mailbox_auto_forwarding_set_mailbox.yml", + "match": false, + "expected": { + "action": "Set-Mailbox", + "log.Workload": "Exchange", + "log.RecordType": 1, + "origin.user": "administrator@example.invalid", + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "mailbox@example.invalid", + "log.ResultStatus": "True", + "actionResult": "success" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "target.user", + "log.o365InboxForwardingChange", + "log.o365SendOnBehalfChange", + "log.o365MailboxForwardingSet" + ] + }, + { + "name": "mailbox-forward-clear-smtp-keep-copy", + "raw": "{\"Operation\":\"Set-Mailbox\",\"Workload\":\"Exchange\",\"RecordType\":1,\"ResultStatus\":\"True\",\"UserId\":\"administrator@example.invalid\",\"ObjectId\":\"mailbox@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\",\"Parameters\":[{\"Name\":\"ForwardingSmtpAddress\",\"Value\":\"\"},{\"Name\":\"DeliverToMailboxAndForward\",\"Value\":\"True\"}]}", + "rule": "office365/mailbox_auto_forwarding_set_mailbox.yml", + "match": false, + "expected": { + "action": "Set-Mailbox", + "log.Workload": "Exchange", + "log.RecordType": 1, + "origin.user": "administrator@example.invalid", + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "mailbox@example.invalid", + "log.ResultStatus": "True", + "actionResult": "success" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "target.user", + "log.o365InboxForwardingChange", + "log.o365SendOnBehalfChange", + "log.o365MailboxForwardingSet" + ] + }, + { + "name": "delegate-Add-MailboxPermission", + "raw": "{\"Operation\":\"Add-MailboxPermission\",\"Workload\":\"Exchange\",\"RecordType\":1,\"ResultStatus\":\"True\",\"UserId\":\"administrator@example.invalid\",\"ObjectId\":\"mailbox@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\",\"Parameters\":[{\"Name\":\"User\",\"Value\":\"delegate@example.invalid\"}]}", + "rule": "office365/mailbox_delegation_abuse.yml", + "match": true, + "expected": { + "action": "Add-MailboxPermission", + "log.Workload": "Exchange", + "log.RecordType": 1, + "origin.user": "administrator@example.invalid", + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "mailbox@example.invalid", + "log.ResultStatus": "True", + "actionResult": "success", + "log.Parameters": "[map[Name:User Value:delegate@example.invalid]]" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "target.user", + "log.o365InboxForwardingChange", + "log.o365MailboxForwardingSet", + "log.o365SendOnBehalfChange" + ] + }, + { + "name": "delegate-Remove-MailboxPermission", + "raw": "{\"Operation\":\"Remove-MailboxPermission\",\"Workload\":\"Exchange\",\"RecordType\":1,\"ResultStatus\":\"True\",\"UserId\":\"administrator@example.invalid\",\"ObjectId\":\"mailbox@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\",\"Parameters\":[{\"Name\":\"User\",\"Value\":\"delegate@example.invalid\"}]}", + "rule": "office365/mailbox_delegation_abuse.yml", + "match": false, + "expected": { + "action": "Remove-MailboxPermission", + "log.Workload": "Exchange", + "log.RecordType": 1, + "origin.user": "administrator@example.invalid", + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "mailbox@example.invalid", + "log.ResultStatus": "True", + "actionResult": "success", + "log.Parameters": "[map[Name:User Value:delegate@example.invalid]]" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "target.user", + "log.o365InboxForwardingChange", + "log.o365MailboxForwardingSet", + "log.o365SendOnBehalfChange" + ] + }, + { + "name": "delegate-Add-RecipientPermission", + "raw": "{\"Operation\":\"Add-RecipientPermission\",\"Workload\":\"Exchange\",\"RecordType\":1,\"ResultStatus\":\"True\",\"UserId\":\"administrator@example.invalid\",\"ObjectId\":\"mailbox@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\",\"Parameters\":[{\"Name\":\"User\",\"Value\":\"delegate@example.invalid\"}]}", + "rule": "office365/mailbox_delegation_abuse.yml", + "match": true, + "expected": { + "action": "Add-RecipientPermission", + "log.Workload": "Exchange", + "log.RecordType": 1, + "origin.user": "administrator@example.invalid", + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "mailbox@example.invalid", + "log.ResultStatus": "True", + "actionResult": "success", + "log.Parameters": "[map[Name:User Value:delegate@example.invalid]]" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "target.user", + "log.o365InboxForwardingChange", + "log.o365MailboxForwardingSet", + "log.o365SendOnBehalfChange" + ] + }, + { + "name": "delegate-Remove-RecipientPermission", + "raw": "{\"Operation\":\"Remove-RecipientPermission\",\"Workload\":\"Exchange\",\"RecordType\":1,\"ResultStatus\":\"True\",\"UserId\":\"administrator@example.invalid\",\"ObjectId\":\"mailbox@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\",\"Parameters\":[{\"Name\":\"User\",\"Value\":\"delegate@example.invalid\"}]}", + "rule": "office365/mailbox_delegation_abuse.yml", + "match": false, + "expected": { + "action": "Remove-RecipientPermission", + "log.Workload": "Exchange", + "log.RecordType": 1, + "origin.user": "administrator@example.invalid", + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "mailbox@example.invalid", + "log.ResultStatus": "True", + "actionResult": "success", + "log.Parameters": "[map[Name:User Value:delegate@example.invalid]]" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "target.user", + "log.o365InboxForwardingChange", + "log.o365MailboxForwardingSet", + "log.o365SendOnBehalfChange" + ] + }, + { + "name": "delegate-GrantSendOnBehalfTo", + "raw": "{\"Operation\":\"Set-Mailbox\",\"Workload\":\"Exchange\",\"RecordType\":1,\"ResultStatus\":\"True\",\"UserId\":\"administrator@example.invalid\",\"ObjectId\":\"mailbox@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\",\"Parameters\":[{\"Name\":\"GrantSendOnBehalfTo\",\"Value\":\"delegate@example.invalid\"}]}", + "rule": "office365/mailbox_delegation_abuse.yml", + "match": true, + "expected": { + "action": "Set-Mailbox", + "log.Workload": "Exchange", + "log.RecordType": 1, + "origin.user": "administrator@example.invalid", + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "mailbox@example.invalid", + "log.ResultStatus": "True", + "actionResult": "success", + "log.Parameters": "[map[Name:GrantSendOnBehalfTo Value:delegate@example.invalid]]", + "log.o365SendOnBehalfChange": "true" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "target.user", + "log.o365InboxForwardingChange", + "log.o365MailboxForwardingSet" + ] + }, + { + "name": "delegate-clear-GrantSendOnBehalfTo", + "raw": "{\"Operation\":\"Set-Mailbox\",\"Workload\":\"Exchange\",\"RecordType\":1,\"ResultStatus\":\"True\",\"UserId\":\"administrator@example.invalid\",\"ObjectId\":\"mailbox@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\",\"Parameters\":[{\"Name\":\"GrantSendOnBehalfTo\",\"Value\":\"\"}]}", + "rule": "office365/mailbox_delegation_abuse.yml", + "match": true, + "expected": { + "action": "Set-Mailbox", + "log.Workload": "Exchange", + "log.RecordType": 1, + "origin.user": "administrator@example.invalid", + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "mailbox@example.invalid", + "log.ResultStatus": "True", + "actionResult": "success", + "log.Parameters": "[map[Name:GrantSendOnBehalfTo Value:]]", + "log.o365SendOnBehalfChange": "true" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "target.user", + "log.o365InboxForwardingChange", + "log.o365MailboxForwardingSet" + ] + }, + { + "name": "folder-Add-MailboxFolderPermission", + "raw": "{\"Operation\":\"Add-MailboxFolderPermission\",\"Workload\":\"Exchange\",\"RecordType\":1,\"ResultStatus\":\"True\",\"UserId\":\"administrator@example.invalid\",\"ObjectId\":\"mailbox@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\",\"Parameters\":[{\"Name\":\"User\",\"Value\":\"delegate@example.invalid\"}]}", + "rule": "office365/awareness_mailbox_folder_permissions.yml", + "match": true, + "expected": { + "action": "Add-MailboxFolderPermission", + "log.Workload": "Exchange", + "log.RecordType": 1, + "origin.user": "administrator@example.invalid", + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "mailbox@example.invalid", + "log.ResultStatus": "True", + "actionResult": "success", + "log.Parameters": "[map[Name:User Value:delegate@example.invalid]]" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "target.user", + "log.o365InboxForwardingChange", + "log.o365MailboxForwardingSet", + "log.o365SendOnBehalfChange" + ] + }, + { + "name": "folder-Set-MailboxFolderPermission", + "raw": "{\"Operation\":\"Set-MailboxFolderPermission\",\"Workload\":\"Exchange\",\"RecordType\":1,\"ResultStatus\":\"True\",\"UserId\":\"administrator@example.invalid\",\"ObjectId\":\"mailbox@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\",\"Parameters\":[{\"Name\":\"User\",\"Value\":\"delegate@example.invalid\"}]}", + "rule": "office365/awareness_mailbox_folder_permissions.yml", + "match": true, + "expected": { + "action": "Set-MailboxFolderPermission", + "log.Workload": "Exchange", + "log.RecordType": 1, + "origin.user": "administrator@example.invalid", + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "mailbox@example.invalid", + "log.ResultStatus": "True", + "actionResult": "success", + "log.Parameters": "[map[Name:User Value:delegate@example.invalid]]" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "target.user", + "log.o365InboxForwardingChange", + "log.o365MailboxForwardingSet", + "log.o365SendOnBehalfChange" + ] + }, + { + "name": "folder-Remove-MailboxFolderPermission", + "raw": "{\"Operation\":\"Remove-MailboxFolderPermission\",\"Workload\":\"Exchange\",\"RecordType\":1,\"ResultStatus\":\"True\",\"UserId\":\"administrator@example.invalid\",\"ObjectId\":\"mailbox@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\",\"Parameters\":[{\"Name\":\"User\",\"Value\":\"delegate@example.invalid\"}]}", + "rule": "office365/awareness_mailbox_folder_permissions.yml", + "match": true, + "expected": { + "action": "Remove-MailboxFolderPermission", + "log.Workload": "Exchange", + "log.RecordType": 1, + "origin.user": "administrator@example.invalid", + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "mailbox@example.invalid", + "log.ResultStatus": "True", + "actionResult": "success", + "log.Parameters": "[map[Name:User Value:delegate@example.invalid]]" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "target.user", + "log.o365InboxForwardingChange", + "log.o365MailboxForwardingSet", + "log.o365SendOnBehalfChange" + ] + }, + { + "name": "folder-AddFolderPermissions", + "raw": "{\"Operation\":\"AddFolderPermissions\",\"Workload\":\"Exchange\",\"RecordType\":2,\"ResultStatus\":\"Succeeded\",\"UserId\":\"administrator@example.invalid\",\"ObjectId\":\"mailbox@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\",\"MailboxOwnerUPN\":\"mailbox@example.invalid\",\"Folder\":{\"Id\":\"folder-fixture-001\",\"Path\":\"/Calendar\"}}", + "rule": "office365/awareness_mailbox_folder_permissions.yml", + "match": true, + "expected": { + "action": "AddFolderPermissions", + "log.Workload": "Exchange", + "log.RecordType": 2, + "origin.user": "administrator@example.invalid", + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "mailbox@example.invalid", + "target.user": "mailbox@example.invalid", + "log.ResultStatus": "Succeeded", + "actionResult": "success", + "log.folderId": "folder-fixture-001", + "log.folderPath": "/Calendar" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "log.MailboxOwnerUPN", + "log.Parameters", + "log.Folder.Id", + "log.Folder.Path", + "log.o365InboxForwardingChange", + "log.o365MailboxForwardingSet", + "log.o365SendOnBehalfChange" + ] + }, + { + "name": "folder-AddFolderPermissions-own-mailbox", + "raw": "{\"Operation\":\"AddFolderPermissions\",\"Workload\":\"Exchange\",\"RecordType\":2,\"ResultStatus\":\"Succeeded\",\"UserId\":\"owner@example.invalid\",\"ObjectId\":\"mailbox@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\",\"MailboxOwnerUPN\":\"owner@example.invalid\",\"Folder\":{\"Id\":\"folder-fixture-001\",\"Path\":\"/Calendar\"}}", + "rule": "office365/awareness_mailbox_folder_permissions.yml", + "match": false, + "expected": { + "action": "AddFolderPermissions", + "log.Workload": "Exchange", + "log.RecordType": 2, + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "mailbox@example.invalid", + "log.ResultStatus": "Succeeded", + "actionResult": "success", + "log.folderId": "folder-fixture-001", + "log.folderPath": "/Calendar", + "origin.user": "owner@example.invalid", + "target.user": "owner@example.invalid" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "log.MailboxOwnerUPN", + "log.Parameters", + "log.Folder.Id", + "log.Folder.Path", + "log.o365InboxForwardingChange", + "log.o365MailboxForwardingSet", + "log.o365SendOnBehalfChange" + ] + }, + { + "name": "folder-ModifyFolderPermissions", + "raw": "{\"Operation\":\"ModifyFolderPermissions\",\"Workload\":\"Exchange\",\"RecordType\":2,\"ResultStatus\":\"Succeeded\",\"UserId\":\"administrator@example.invalid\",\"ObjectId\":\"mailbox@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\",\"MailboxOwnerUPN\":\"mailbox@example.invalid\",\"Folder\":{\"Id\":\"folder-fixture-001\",\"Path\":\"/Calendar\"}}", + "rule": "office365/awareness_mailbox_folder_permissions.yml", + "match": true, + "expected": { + "action": "ModifyFolderPermissions", + "log.Workload": "Exchange", + "log.RecordType": 2, + "origin.user": "administrator@example.invalid", + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "mailbox@example.invalid", + "target.user": "mailbox@example.invalid", + "log.ResultStatus": "Succeeded", + "actionResult": "success", + "log.folderId": "folder-fixture-001", + "log.folderPath": "/Calendar" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "log.MailboxOwnerUPN", + "log.Parameters", + "log.Folder.Id", + "log.Folder.Path", + "log.o365InboxForwardingChange", + "log.o365MailboxForwardingSet", + "log.o365SendOnBehalfChange" + ] + }, + { + "name": "folder-RemoveFolderPermissions", + "raw": "{\"Operation\":\"RemoveFolderPermissions\",\"Workload\":\"Exchange\",\"RecordType\":2,\"ResultStatus\":\"Succeeded\",\"UserId\":\"administrator@example.invalid\",\"ObjectId\":\"mailbox@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\",\"MailboxOwnerUPN\":\"mailbox@example.invalid\",\"Folder\":{\"Id\":\"folder-fixture-001\",\"Path\":\"/Calendar\"}}", + "rule": "office365/awareness_mailbox_folder_permissions.yml", + "match": true, + "expected": { + "action": "RemoveFolderPermissions", + "log.Workload": "Exchange", + "log.RecordType": 2, + "origin.user": "administrator@example.invalid", + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "mailbox@example.invalid", + "target.user": "mailbox@example.invalid", + "log.ResultStatus": "Succeeded", + "actionResult": "success", + "log.folderId": "folder-fixture-001", + "log.folderPath": "/Calendar" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "log.MailboxOwnerUPN", + "log.Parameters", + "log.Folder.Id", + "log.Folder.Path", + "log.o365InboxForwardingChange", + "log.o365MailboxForwardingSet", + "log.o365SendOnBehalfChange" + ] + }, + { + "name": "folder-ModifyFolderPermissions-microsoft-service", + "raw": "{\"Operation\":\"ModifyFolderPermissions\",\"Workload\":\"Exchange\",\"RecordType\":2,\"ResultStatus\":\"Succeeded\",\"UserId\":\"S-1-5-21-1111111111-2222222222-3333333333-4444444\",\"ObjectId\":\"group@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\",\"MailboxOwnerUPN\":\"group@example.invalid\",\"Folder\":{\"Id\":\"folder-fixture-001\",\"Path\":\"/Calendar\"},\"ExternalAccess\":true,\"LogonType\":1,\"ClientInfoString\":\"Client=WebServices;Action=ConfigureGroupMailbox\"}", + "rule": "office365/awareness_mailbox_folder_permissions.yml", + "match": false, + "expected": { + "action": "ModifyFolderPermissions", + "log.Workload": "Exchange", + "log.RecordType": 2, + "origin.user": "S-1-5-21-1111111111-2222222222-3333333333-4444444", + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "group@example.invalid", + "target.user": "group@example.invalid", + "log.ResultStatus": "Succeeded", + "actionResult": "success", + "log.folderId": "folder-fixture-001", + "log.folderPath": "/Calendar", + "log.ExternalAccess": true + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "log.MailboxOwnerUPN", + "log.Parameters", + "log.Folder.Id", + "log.Folder.Path", + "log.o365InboxForwardingChange", + "log.o365MailboxForwardingSet", + "log.o365SendOnBehalfChange" + ] + }, + { + "name": "folder-ModifyFolderPermissions-external-named-actor", + "raw": "{\"Operation\":\"ModifyFolderPermissions\",\"Workload\":\"Exchange\",\"RecordType\":2,\"ResultStatus\":\"Succeeded\",\"UserId\":\"partner-admin@example.invalid\",\"ObjectId\":\"group@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\",\"MailboxOwnerUPN\":\"group@example.invalid\",\"Folder\":{\"Id\":\"folder-fixture-001\",\"Path\":\"/Calendar\"},\"ExternalAccess\":true,\"LogonType\":1,\"ClientInfoString\":\"Client=WebServices;Action=ConfigureGroupMailbox\"}", + "rule": "office365/awareness_mailbox_folder_permissions.yml", + "match": true, + "expected": { + "action": "ModifyFolderPermissions", + "log.Workload": "Exchange", + "log.RecordType": 2, + "origin.user": "partner-admin@example.invalid", + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "group@example.invalid", + "target.user": "group@example.invalid", + "log.ResultStatus": "Succeeded", + "actionResult": "success", + "log.folderId": "folder-fixture-001", + "log.folderPath": "/Calendar", + "log.ExternalAccess": true + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "log.MailboxOwnerUPN", + "log.Parameters", + "log.Folder.Id", + "log.Folder.Path", + "log.o365InboxForwardingChange", + "log.o365MailboxForwardingSet", + "log.o365SendOnBehalfChange" + ] + }, + { + "name": "folder-ModifyFolderPermissions-internal-sid-actor", + "raw": "{\"Operation\":\"ModifyFolderPermissions\",\"Workload\":\"Exchange\",\"RecordType\":2,\"ResultStatus\":\"Succeeded\",\"UserId\":\"S-1-5-21-1111111111-2222222222-3333333333-4444444\",\"ObjectId\":\"group@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\",\"MailboxOwnerUPN\":\"group@example.invalid\",\"Folder\":{\"Id\":\"folder-fixture-001\",\"Path\":\"/Calendar\"},\"ExternalAccess\":false,\"LogonType\":1,\"ClientInfoString\":\"Client=WebServices;Action=ConfigureGroupMailbox\"}", + "rule": "office365/awareness_mailbox_folder_permissions.yml", + "match": true, + "expected": { + "action": "ModifyFolderPermissions", + "log.Workload": "Exchange", + "log.RecordType": 2, + "origin.user": "S-1-5-21-1111111111-2222222222-3333333333-4444444", + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "group@example.invalid", + "target.user": "group@example.invalid", + "log.ResultStatus": "Succeeded", + "actionResult": "success", + "log.folderId": "folder-fixture-001", + "log.folderPath": "/Calendar", + "log.ExternalAccess": false + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "log.MailboxOwnerUPN", + "log.Parameters", + "log.Folder.Id", + "log.Folder.Path", + "log.o365InboxForwardingChange", + "log.o365MailboxForwardingSet", + "log.o365SendOnBehalfChange" + ] + }, + { + "name": "folder-ModifyFolderPermissions-owner-logon", + "raw": "{\"Operation\":\"ModifyFolderPermissions\",\"Workload\":\"Exchange\",\"RecordType\":2,\"ResultStatus\":\"Succeeded\",\"UserId\":\"Owner@Example.invalid\",\"ObjectId\":\"owner@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\",\"MailboxOwnerUPN\":\"owner@example.invalid\",\"Folder\":{\"Id\":\"folder-fixture-001\",\"Path\":\"/Calendar\"},\"LogonType\":0,\"ExternalAccess\":false}", + "rule": "office365/awareness_mailbox_folder_permissions.yml", + "match": false, + "expected": { + "action": "ModifyFolderPermissions", + "log.Workload": "Exchange", + "log.RecordType": 2, + "origin.user": "Owner@Example.invalid", + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "owner@example.invalid", + "target.user": "owner@example.invalid", + "log.ResultStatus": "Succeeded", + "actionResult": "success", + "log.folderId": "folder-fixture-001", + "log.folderPath": "/Calendar", + "log.LogonType": 0, + "log.ExternalAccess": false + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "log.MailboxOwnerUPN", + "log.Parameters", + "log.Folder.Id", + "log.Folder.Path", + "log.o365InboxForwardingChange", + "log.o365MailboxForwardingSet", + "log.o365SendOnBehalfChange" + ] + }, + { + "name": "calendar-UpdateCalendarDelegation", + "raw": "{\"Operation\":\"UpdateCalendarDelegation\",\"Workload\":\"Exchange\",\"RecordType\":2,\"ResultStatus\":\"Succeeded\",\"UserId\":\"administrator@example.invalid\",\"ObjectId\":\"mailbox@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\",\"MailboxOwnerUPN\":\"mailbox@example.invalid\"}", + "rule": "office365/awareness_calendar_delegation.yml", + "match": true, + "expected": { + "action": "UpdateCalendarDelegation", + "log.Workload": "Exchange", + "log.RecordType": 2, + "origin.user": "administrator@example.invalid", + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "mailbox@example.invalid", + "target.user": "mailbox@example.invalid", + "log.ResultStatus": "Succeeded", + "actionResult": "success" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "log.MailboxOwnerUPN", + "log.Parameters", + "log.o365InboxForwardingChange", + "log.o365MailboxForwardingSet", + "log.o365SendOnBehalfChange" + ] + }, + { + "name": "connector-New-InboundConnector", + "raw": "{\"Operation\":\"New-InboundConnector\",\"Workload\":\"Exchange\",\"RecordType\":1,\"ResultStatus\":\"True\",\"UserId\":\"administrator@example.invalid\",\"ObjectId\":\"mailbox@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\",\"Parameters\":[{\"Name\":\"Identity\",\"Value\":\"Administrative connector\"}]}", + "rule": "office365/awareness_mail_connectors.yml", + "match": true, + "expected": { + "action": "New-InboundConnector", + "log.Workload": "Exchange", + "log.RecordType": 1, + "origin.user": "administrator@example.invalid", + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "mailbox@example.invalid", + "log.ResultStatus": "True", + "actionResult": "success", + "log.Parameters": "[map[Name:Identity Value:Administrative connector]]" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "target.user", + "log.o365InboxForwardingChange", + "log.o365MailboxForwardingSet", + "log.o365SendOnBehalfChange" + ] + }, + { + "name": "connector-Set-InboundConnector", + "raw": "{\"Operation\":\"Set-InboundConnector\",\"Workload\":\"Exchange\",\"RecordType\":1,\"ResultStatus\":\"True\",\"UserId\":\"administrator@example.invalid\",\"ObjectId\":\"mailbox@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\",\"Parameters\":[{\"Name\":\"Identity\",\"Value\":\"Administrative connector\"}]}", + "rule": "office365/awareness_mail_connectors.yml", + "match": true, + "expected": { + "action": "Set-InboundConnector", + "log.Workload": "Exchange", + "log.RecordType": 1, + "origin.user": "administrator@example.invalid", + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "mailbox@example.invalid", + "log.ResultStatus": "True", + "actionResult": "success", + "log.Parameters": "[map[Name:Identity Value:Administrative connector]]" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "target.user", + "log.o365InboxForwardingChange", + "log.o365MailboxForwardingSet", + "log.o365SendOnBehalfChange" + ] + }, + { + "name": "connector-Remove-InboundConnector", + "raw": "{\"Operation\":\"Remove-InboundConnector\",\"Workload\":\"Exchange\",\"RecordType\":1,\"ResultStatus\":\"True\",\"UserId\":\"administrator@example.invalid\",\"ObjectId\":\"mailbox@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\",\"Parameters\":[{\"Name\":\"Identity\",\"Value\":\"Administrative connector\"}]}", + "rule": "office365/awareness_mail_connectors.yml", + "match": true, + "expected": { + "action": "Remove-InboundConnector", + "log.Workload": "Exchange", + "log.RecordType": 1, + "origin.user": "administrator@example.invalid", + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "mailbox@example.invalid", + "log.ResultStatus": "True", + "actionResult": "success", + "log.Parameters": "[map[Name:Identity Value:Administrative connector]]" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "target.user", + "log.o365InboxForwardingChange", + "log.o365MailboxForwardingSet", + "log.o365SendOnBehalfChange" + ] + }, + { + "name": "connector-New-OutboundConnector", + "raw": "{\"Operation\":\"New-OutboundConnector\",\"Workload\":\"Exchange\",\"RecordType\":1,\"ResultStatus\":\"True\",\"UserId\":\"administrator@example.invalid\",\"ObjectId\":\"mailbox@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\",\"Parameters\":[{\"Name\":\"Identity\",\"Value\":\"Administrative connector\"}]}", + "rule": "office365/awareness_mail_connectors.yml", + "match": true, + "expected": { + "action": "New-OutboundConnector", + "log.Workload": "Exchange", + "log.RecordType": 1, + "origin.user": "administrator@example.invalid", + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "mailbox@example.invalid", + "log.ResultStatus": "True", + "actionResult": "success", + "log.Parameters": "[map[Name:Identity Value:Administrative connector]]" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "target.user", + "log.o365InboxForwardingChange", + "log.o365MailboxForwardingSet", + "log.o365SendOnBehalfChange" + ] + }, + { + "name": "connector-Set-OutboundConnector", + "raw": "{\"Operation\":\"Set-OutboundConnector\",\"Workload\":\"Exchange\",\"RecordType\":1,\"ResultStatus\":\"True\",\"UserId\":\"administrator@example.invalid\",\"ObjectId\":\"mailbox@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\",\"Parameters\":[{\"Name\":\"Identity\",\"Value\":\"Administrative connector\"}]}", + "rule": "office365/awareness_mail_connectors.yml", + "match": true, + "expected": { + "action": "Set-OutboundConnector", + "log.Workload": "Exchange", + "log.RecordType": 1, + "origin.user": "administrator@example.invalid", + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "mailbox@example.invalid", + "log.ResultStatus": "True", + "actionResult": "success", + "log.Parameters": "[map[Name:Identity Value:Administrative connector]]" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "target.user", + "log.o365InboxForwardingChange", + "log.o365MailboxForwardingSet", + "log.o365SendOnBehalfChange" + ] + }, + { + "name": "connector-Remove-OutboundConnector", + "raw": "{\"Operation\":\"Remove-OutboundConnector\",\"Workload\":\"Exchange\",\"RecordType\":1,\"ResultStatus\":\"True\",\"UserId\":\"administrator@example.invalid\",\"ObjectId\":\"mailbox@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\",\"Parameters\":[{\"Name\":\"Identity\",\"Value\":\"Administrative connector\"}]}", + "rule": "office365/awareness_mail_connectors.yml", + "match": true, + "expected": { + "action": "Remove-OutboundConnector", + "log.Workload": "Exchange", + "log.RecordType": 1, + "origin.user": "administrator@example.invalid", + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "mailbox@example.invalid", + "log.ResultStatus": "True", + "actionResult": "success", + "log.Parameters": "[map[Name:Identity Value:Administrative connector]]" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "target.user", + "log.o365InboxForwardingChange", + "log.o365MailboxForwardingSet", + "log.o365SendOnBehalfChange" + ] + }, + { + "name": "client-access-Set-CASMailbox", + "raw": "{\"Operation\":\"Set-CASMailbox\",\"Workload\":\"Exchange\",\"RecordType\":1,\"ResultStatus\":\"True\",\"UserId\":\"administrator@example.invalid\",\"ObjectId\":\"mailbox@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\",\"Parameters\":[{\"Name\":\"Identity\",\"Value\":\"administrative-fixture\"}]}", + "rule": "office365/awareness_mailbox_client_access.yml", + "match": true, + "expected": { + "action": "Set-CASMailbox", + "log.Workload": "Exchange", + "log.RecordType": 1, + "origin.user": "administrator@example.invalid", + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "mailbox@example.invalid", + "log.ResultStatus": "True", + "actionResult": "success", + "log.Parameters": "[map[Name:Identity Value:administrative-fixture]]" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "target.user", + "log.o365InboxForwardingChange", + "log.o365MailboxForwardingSet", + "log.o365SendOnBehalfChange" + ] + }, + { + "name": "collection_microsoft_365_new_inbox_rule-failed-operation", + "raw": "{\"Operation\":\"New-InboxRule\",\"Workload\":\"Exchange\",\"RecordType\":1,\"ResultStatus\":\"False\",\"UserId\":\"administrator@example.invalid\",\"ObjectId\":\"mailbox@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\",\"Parameters\":[{\"Name\":\"Name\",\"Value\":\"Administrative rule\"}]}", + "rule": "office365/collection_microsoft_365_new_inbox_rule.yml", + "match": false, + "expected": { + "action": "New-InboxRule", + "log.Workload": "Exchange", + "log.RecordType": 1, + "origin.user": "administrator@example.invalid", + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "mailbox@example.invalid", + "log.ResultStatus": "False", + "actionResult": "failure", + "log.Parameters": "[map[Name:Name Value:Administrative rule]]" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "target.user", + "log.o365InboxForwardingChange", + "log.o365MailboxForwardingSet", + "log.o365SendOnBehalfChange" + ] + }, + { + "name": "collection_microsoft_365_new_inbox_rule-wrong-workload", + "raw": "{\"Operation\":\"New-InboxRule\",\"Workload\":\"SharePoint\",\"RecordType\":1,\"ResultStatus\":\"True\",\"UserId\":\"administrator@example.invalid\",\"ObjectId\":\"mailbox@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\",\"Parameters\":[{\"Name\":\"Name\",\"Value\":\"Administrative rule\"}]}", + "rule": "office365/collection_microsoft_365_new_inbox_rule.yml", + "match": false, + "expected": { + "action": "New-InboxRule", + "log.Workload": "SharePoint", + "log.RecordType": 1, + "origin.user": "administrator@example.invalid", + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "mailbox@example.invalid", + "log.ResultStatus": "True", + "actionResult": "success", + "log.Parameters": "[map[Name:Name Value:Administrative rule]]" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "target.user", + "log.o365InboxForwardingChange", + "log.o365MailboxForwardingSet", + "log.o365SendOnBehalfChange" + ] + }, + { + "name": "collection_microsoft_365_new_inbox_rule-missing-optional-identities", + "raw": "{\"Operation\":\"New-InboxRule\",\"Workload\":\"Exchange\",\"RecordType\":1,\"ResultStatus\":\"True\",\"Parameters\":[{\"Name\":\"Name\",\"Value\":\"Administrative rule\"}]}", + "rule": "office365/collection_microsoft_365_new_inbox_rule.yml", + "match": true, + "expected": { + "action": "New-InboxRule", + "log.Workload": "Exchange", + "log.RecordType": 1, + "log.ResultStatus": "True", + "actionResult": "success", + "log.Parameters": "[map[Name:Name Value:Administrative rule]]" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "origin.user", + "log.OrganizationId", + "log.ObjectId", + "target.user", + "log.o365InboxForwardingChange", + "log.o365MailboxForwardingSet", + "log.o365SendOnBehalfChange" + ] + }, + { + "name": "mail_forwarding_rules-failed-operation", + "raw": "{\"Operation\":\"New-InboxRule\",\"Workload\":\"Exchange\",\"RecordType\":1,\"ResultStatus\":\"False\",\"UserId\":\"administrator@example.invalid\",\"ObjectId\":\"mailbox@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\",\"Parameters\":[{\"Name\":\"ForwardTo\",\"Value\":\"delegate@example.invalid\"}]}", + "rule": "office365/mail_forwarding_rules.yml", + "match": false, + "expected": { + "action": "New-InboxRule", + "log.Workload": "Exchange", + "log.RecordType": 1, + "origin.user": "administrator@example.invalid", + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "mailbox@example.invalid", + "log.ResultStatus": "False", + "actionResult": "failure", + "log.Parameters": "[map[Name:ForwardTo Value:delegate@example.invalid]]", + "log.o365InboxForwardingChange": "true" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "target.user", + "log.o365MailboxForwardingSet", + "log.o365SendOnBehalfChange" + ] + }, + { + "name": "mail_forwarding_rules-wrong-workload", + "raw": "{\"Operation\":\"New-InboxRule\",\"Workload\":\"SharePoint\",\"RecordType\":1,\"ResultStatus\":\"True\",\"UserId\":\"administrator@example.invalid\",\"ObjectId\":\"mailbox@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\",\"Parameters\":[{\"Name\":\"ForwardTo\",\"Value\":\"delegate@example.invalid\"}]}", + "rule": "office365/mail_forwarding_rules.yml", + "match": false, + "expected": { + "action": "New-InboxRule", + "log.Workload": "SharePoint", + "log.RecordType": 1, + "origin.user": "administrator@example.invalid", + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "mailbox@example.invalid", + "log.ResultStatus": "True", + "actionResult": "success", + "log.Parameters": "[map[Name:ForwardTo Value:delegate@example.invalid]]" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "target.user", + "log.o365InboxForwardingChange", + "log.o365MailboxForwardingSet", + "log.o365SendOnBehalfChange" + ] + }, + { + "name": "mail_forwarding_rules-missing-optional-identities", + "raw": "{\"Operation\":\"New-InboxRule\",\"Workload\":\"Exchange\",\"RecordType\":1,\"ResultStatus\":\"True\",\"Parameters\":[{\"Name\":\"ForwardTo\",\"Value\":\"delegate@example.invalid\"}]}", + "rule": "office365/mail_forwarding_rules.yml", + "match": true, + "expected": { + "action": "New-InboxRule", + "log.Workload": "Exchange", + "log.RecordType": 1, + "log.ResultStatus": "True", + "actionResult": "success", + "log.Parameters": "[map[Name:ForwardTo Value:delegate@example.invalid]]", + "log.o365InboxForwardingChange": "true" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "origin.user", + "log.OrganizationId", + "log.ObjectId", + "target.user", + "log.o365MailboxForwardingSet", + "log.o365SendOnBehalfChange" + ] + }, + { + "name": "mailbox_auto_forwarding_set_mailbox-failed-operation", + "raw": "{\"Operation\":\"Set-Mailbox\",\"Workload\":\"Exchange\",\"RecordType\":1,\"ResultStatus\":\"False\",\"UserId\":\"administrator@example.invalid\",\"ObjectId\":\"mailbox@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\",\"Parameters\":[{\"Name\":\"ForwardingAddress\",\"Value\":\"recipient@example.invalid\"}]}", + "rule": "office365/mailbox_auto_forwarding_set_mailbox.yml", + "match": false, + "expected": { + "action": "Set-Mailbox", + "log.Workload": "Exchange", + "log.RecordType": 1, + "origin.user": "administrator@example.invalid", + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "mailbox@example.invalid", + "log.ResultStatus": "False", + "actionResult": "failure", + "log.Parameters": "[map[Name:ForwardingAddress Value:recipient@example.invalid]]", + "log.o365MailboxForwardingSet": "true" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "target.user", + "log.o365InboxForwardingChange", + "log.o365SendOnBehalfChange" + ] + }, + { + "name": "mailbox_auto_forwarding_set_mailbox-wrong-workload", + "raw": "{\"Operation\":\"Set-Mailbox\",\"Workload\":\"SharePoint\",\"RecordType\":1,\"ResultStatus\":\"True\",\"UserId\":\"administrator@example.invalid\",\"ObjectId\":\"mailbox@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\",\"Parameters\":[{\"Name\":\"ForwardingAddress\",\"Value\":\"recipient@example.invalid\"}]}", + "rule": "office365/mailbox_auto_forwarding_set_mailbox.yml", + "match": false, + "expected": { + "action": "Set-Mailbox", + "log.Workload": "SharePoint", + "log.RecordType": 1, + "origin.user": "administrator@example.invalid", + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "mailbox@example.invalid", + "log.ResultStatus": "True", + "actionResult": "success", + "log.Parameters": "[map[Name:ForwardingAddress Value:recipient@example.invalid]]" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "target.user", + "log.o365InboxForwardingChange", + "log.o365MailboxForwardingSet", + "log.o365SendOnBehalfChange" + ] + }, + { + "name": "mailbox_auto_forwarding_set_mailbox-missing-optional-identities", + "raw": "{\"Operation\":\"Set-Mailbox\",\"Workload\":\"Exchange\",\"RecordType\":1,\"ResultStatus\":\"True\",\"Parameters\":[{\"Name\":\"ForwardingAddress\",\"Value\":\"recipient@example.invalid\"}]}", + "rule": "office365/mailbox_auto_forwarding_set_mailbox.yml", + "match": true, + "expected": { + "action": "Set-Mailbox", + "log.Workload": "Exchange", + "log.RecordType": 1, + "log.ResultStatus": "True", + "actionResult": "success", + "log.Parameters": "[map[Name:ForwardingAddress Value:recipient@example.invalid]]", + "log.o365MailboxForwardingSet": "true" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "origin.user", + "log.OrganizationId", + "log.ObjectId", + "target.user", + "log.o365InboxForwardingChange", + "log.o365SendOnBehalfChange" + ] + }, + { + "name": "mailbox_delegation_abuse-failed-operation", + "raw": "{\"Operation\":\"Add-MailboxPermission\",\"Workload\":\"Exchange\",\"RecordType\":1,\"ResultStatus\":\"False\",\"UserId\":\"administrator@example.invalid\",\"ObjectId\":\"mailbox@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\",\"Parameters\":[{\"Name\":\"User\",\"Value\":\"delegate@example.invalid\"}]}", + "rule": "office365/mailbox_delegation_abuse.yml", + "match": false, + "expected": { + "action": "Add-MailboxPermission", + "log.Workload": "Exchange", + "log.RecordType": 1, + "origin.user": "administrator@example.invalid", + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "mailbox@example.invalid", + "log.ResultStatus": "False", + "actionResult": "failure", + "log.Parameters": "[map[Name:User Value:delegate@example.invalid]]" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "target.user", + "log.o365InboxForwardingChange", + "log.o365MailboxForwardingSet", + "log.o365SendOnBehalfChange" + ] + }, + { + "name": "mailbox_delegation_abuse-wrong-workload", + "raw": "{\"Operation\":\"Add-MailboxPermission\",\"Workload\":\"SharePoint\",\"RecordType\":1,\"ResultStatus\":\"True\",\"UserId\":\"administrator@example.invalid\",\"ObjectId\":\"mailbox@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\",\"Parameters\":[{\"Name\":\"User\",\"Value\":\"delegate@example.invalid\"}]}", + "rule": "office365/mailbox_delegation_abuse.yml", + "match": false, + "expected": { + "action": "Add-MailboxPermission", + "log.Workload": "SharePoint", + "log.RecordType": 1, + "origin.user": "administrator@example.invalid", + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "mailbox@example.invalid", + "log.ResultStatus": "True", + "actionResult": "success", + "log.Parameters": "[map[Name:User Value:delegate@example.invalid]]" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "target.user", + "log.o365InboxForwardingChange", + "log.o365MailboxForwardingSet", + "log.o365SendOnBehalfChange" + ] + }, + { + "name": "mailbox_delegation_abuse-missing-optional-identities", + "raw": "{\"Operation\":\"Add-MailboxPermission\",\"Workload\":\"Exchange\",\"RecordType\":1,\"ResultStatus\":\"True\",\"Parameters\":[{\"Name\":\"User\",\"Value\":\"delegate@example.invalid\"}]}", + "rule": "office365/mailbox_delegation_abuse.yml", + "match": true, + "expected": { + "action": "Add-MailboxPermission", + "log.Workload": "Exchange", + "log.RecordType": 1, + "log.ResultStatus": "True", + "actionResult": "success", + "log.Parameters": "[map[Name:User Value:delegate@example.invalid]]" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "origin.user", + "log.OrganizationId", + "log.ObjectId", + "target.user", + "log.o365InboxForwardingChange", + "log.o365MailboxForwardingSet", + "log.o365SendOnBehalfChange" + ] + }, + { + "name": "awareness_mailbox_folder_permissions-failed-operation", + "raw": "{\"Operation\":\"Add-MailboxFolderPermission\",\"Workload\":\"Exchange\",\"RecordType\":1,\"ResultStatus\":\"False\",\"UserId\":\"administrator@example.invalid\",\"ObjectId\":\"mailbox@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\",\"Parameters\":[{\"Name\":\"User\",\"Value\":\"delegate@example.invalid\"}]}", + "rule": "office365/awareness_mailbox_folder_permissions.yml", + "match": false, + "expected": { + "action": "Add-MailboxFolderPermission", + "log.Workload": "Exchange", + "log.RecordType": 1, + "origin.user": "administrator@example.invalid", + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "mailbox@example.invalid", + "log.ResultStatus": "False", + "actionResult": "failure", + "log.Parameters": "[map[Name:User Value:delegate@example.invalid]]" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "target.user", + "log.o365InboxForwardingChange", + "log.o365MailboxForwardingSet", + "log.o365SendOnBehalfChange" + ] + }, + { + "name": "awareness_mailbox_folder_permissions-wrong-workload", + "raw": "{\"Operation\":\"Add-MailboxFolderPermission\",\"Workload\":\"SharePoint\",\"RecordType\":1,\"ResultStatus\":\"True\",\"UserId\":\"administrator@example.invalid\",\"ObjectId\":\"mailbox@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\",\"Parameters\":[{\"Name\":\"User\",\"Value\":\"delegate@example.invalid\"}]}", + "rule": "office365/awareness_mailbox_folder_permissions.yml", + "match": false, + "expected": { + "action": "Add-MailboxFolderPermission", + "log.Workload": "SharePoint", + "log.RecordType": 1, + "origin.user": "administrator@example.invalid", + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "mailbox@example.invalid", + "log.ResultStatus": "True", + "actionResult": "success", + "log.Parameters": "[map[Name:User Value:delegate@example.invalid]]" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "target.user", + "log.o365InboxForwardingChange", + "log.o365MailboxForwardingSet", + "log.o365SendOnBehalfChange" + ] + }, + { + "name": "awareness_mailbox_folder_permissions-missing-optional-identities", + "raw": "{\"Operation\":\"Add-MailboxFolderPermission\",\"Workload\":\"Exchange\",\"RecordType\":1,\"ResultStatus\":\"True\",\"Parameters\":[{\"Name\":\"User\",\"Value\":\"delegate@example.invalid\"}]}", + "rule": "office365/awareness_mailbox_folder_permissions.yml", + "match": true, + "expected": { + "action": "Add-MailboxFolderPermission", + "log.Workload": "Exchange", + "log.RecordType": 1, + "log.ResultStatus": "True", + "actionResult": "success", + "log.Parameters": "[map[Name:User Value:delegate@example.invalid]]" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "origin.user", + "log.OrganizationId", + "log.ObjectId", + "target.user", + "log.o365InboxForwardingChange", + "log.o365MailboxForwardingSet", + "log.o365SendOnBehalfChange" + ] + }, + { + "name": "awareness_calendar_delegation-failed-operation", + "raw": "{\"Operation\":\"UpdateCalendarDelegation\",\"Workload\":\"Exchange\",\"RecordType\":2,\"ResultStatus\":\"Failed\",\"UserId\":\"administrator@example.invalid\",\"ObjectId\":\"mailbox@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\",\"MailboxOwnerUPN\":\"mailbox@example.invalid\"}", + "rule": "office365/awareness_calendar_delegation.yml", + "match": false, + "expected": { + "action": "UpdateCalendarDelegation", + "log.Workload": "Exchange", + "log.RecordType": 2, + "origin.user": "administrator@example.invalid", + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "mailbox@example.invalid", + "target.user": "mailbox@example.invalid", + "log.ResultStatus": "Failed", + "actionResult": "failure" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "log.MailboxOwnerUPN", + "log.Parameters", + "log.o365InboxForwardingChange", + "log.o365MailboxForwardingSet", + "log.o365SendOnBehalfChange" + ] + }, + { + "name": "awareness_calendar_delegation-wrong-workload", + "raw": "{\"Operation\":\"UpdateCalendarDelegation\",\"Workload\":\"SharePoint\",\"RecordType\":2,\"ResultStatus\":\"Succeeded\",\"UserId\":\"administrator@example.invalid\",\"ObjectId\":\"mailbox@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\",\"MailboxOwnerUPN\":\"mailbox@example.invalid\"}", + "rule": "office365/awareness_calendar_delegation.yml", + "match": false, + "expected": { + "action": "UpdateCalendarDelegation", + "log.Workload": "SharePoint", + "log.RecordType": 2, + "origin.user": "administrator@example.invalid", + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "mailbox@example.invalid", + "target.user": "mailbox@example.invalid", + "log.ResultStatus": "Succeeded", + "actionResult": "success" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "log.MailboxOwnerUPN", + "log.Parameters", + "log.o365InboxForwardingChange", + "log.o365MailboxForwardingSet", + "log.o365SendOnBehalfChange" + ] + }, + { + "name": "awareness_calendar_delegation-missing-optional-identities", + "raw": "{\"Operation\":\"UpdateCalendarDelegation\",\"Workload\":\"Exchange\",\"RecordType\":2,\"ResultStatus\":\"Succeeded\"}", + "rule": "office365/awareness_calendar_delegation.yml", + "match": true, + "expected": { + "action": "UpdateCalendarDelegation", + "log.Workload": "Exchange", + "log.RecordType": 2, + "log.ResultStatus": "Succeeded", + "actionResult": "success" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "origin.user", + "log.OrganizationId", + "log.ObjectId", + "target.user", + "log.Parameters", + "log.o365InboxForwardingChange", + "log.o365MailboxForwardingSet", + "log.o365SendOnBehalfChange" + ] + }, + { + "name": "awareness_mail_connectors-failed-operation", + "raw": "{\"Operation\":\"New-InboundConnector\",\"Workload\":\"Exchange\",\"RecordType\":1,\"ResultStatus\":\"False\",\"UserId\":\"administrator@example.invalid\",\"ObjectId\":\"mailbox@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\",\"Parameters\":[{\"Name\":\"Identity\",\"Value\":\"Administrative connector\"}]}", + "rule": "office365/awareness_mail_connectors.yml", + "match": false, + "expected": { + "action": "New-InboundConnector", + "log.Workload": "Exchange", + "log.RecordType": 1, + "origin.user": "administrator@example.invalid", + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "mailbox@example.invalid", + "log.ResultStatus": "False", + "actionResult": "failure", + "log.Parameters": "[map[Name:Identity Value:Administrative connector]]" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "target.user", + "log.o365InboxForwardingChange", + "log.o365MailboxForwardingSet", + "log.o365SendOnBehalfChange" + ] + }, + { + "name": "awareness_mail_connectors-wrong-workload", + "raw": "{\"Operation\":\"New-InboundConnector\",\"Workload\":\"SharePoint\",\"RecordType\":1,\"ResultStatus\":\"True\",\"UserId\":\"administrator@example.invalid\",\"ObjectId\":\"mailbox@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\",\"Parameters\":[{\"Name\":\"Identity\",\"Value\":\"Administrative connector\"}]}", + "rule": "office365/awareness_mail_connectors.yml", + "match": false, + "expected": { + "action": "New-InboundConnector", + "log.Workload": "SharePoint", + "log.RecordType": 1, + "origin.user": "administrator@example.invalid", + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "mailbox@example.invalid", + "log.ResultStatus": "True", + "actionResult": "success", + "log.Parameters": "[map[Name:Identity Value:Administrative connector]]" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "target.user", + "log.o365InboxForwardingChange", + "log.o365MailboxForwardingSet", + "log.o365SendOnBehalfChange" + ] + }, + { + "name": "awareness_mail_connectors-missing-optional-identities", + "raw": "{\"Operation\":\"New-InboundConnector\",\"Workload\":\"Exchange\",\"RecordType\":1,\"ResultStatus\":\"True\",\"Parameters\":[{\"Name\":\"Identity\",\"Value\":\"Administrative connector\"}]}", + "rule": "office365/awareness_mail_connectors.yml", + "match": true, + "expected": { + "action": "New-InboundConnector", + "log.Workload": "Exchange", + "log.RecordType": 1, + "log.ResultStatus": "True", + "actionResult": "success", + "log.Parameters": "[map[Name:Identity Value:Administrative connector]]" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "origin.user", + "log.OrganizationId", + "log.ObjectId", + "target.user", + "log.o365InboxForwardingChange", + "log.o365MailboxForwardingSet", + "log.o365SendOnBehalfChange" + ] + }, + { + "name": "awareness_mailbox_client_access-failed-operation", + "raw": "{\"Operation\":\"Set-CASMailbox\",\"Workload\":\"Exchange\",\"RecordType\":1,\"ResultStatus\":\"False\",\"UserId\":\"administrator@example.invalid\",\"ObjectId\":\"mailbox@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\",\"Parameters\":[{\"Name\":\"Identity\",\"Value\":\"administrative-fixture\"}]}", + "rule": "office365/awareness_mailbox_client_access.yml", + "match": false, + "expected": { + "action": "Set-CASMailbox", + "log.Workload": "Exchange", + "log.RecordType": 1, + "origin.user": "administrator@example.invalid", + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "mailbox@example.invalid", + "log.ResultStatus": "False", + "actionResult": "failure", + "log.Parameters": "[map[Name:Identity Value:administrative-fixture]]" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "target.user", + "log.o365InboxForwardingChange", + "log.o365MailboxForwardingSet", + "log.o365SendOnBehalfChange" + ] + }, + { + "name": "awareness_mailbox_client_access-wrong-workload", + "raw": "{\"Operation\":\"Set-CASMailbox\",\"Workload\":\"SharePoint\",\"RecordType\":1,\"ResultStatus\":\"True\",\"UserId\":\"administrator@example.invalid\",\"ObjectId\":\"mailbox@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\",\"Parameters\":[{\"Name\":\"Identity\",\"Value\":\"administrative-fixture\"}]}", + "rule": "office365/awareness_mailbox_client_access.yml", + "match": false, + "expected": { + "action": "Set-CASMailbox", + "log.Workload": "SharePoint", + "log.RecordType": 1, + "origin.user": "administrator@example.invalid", + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "mailbox@example.invalid", + "log.ResultStatus": "True", + "actionResult": "success", + "log.Parameters": "[map[Name:Identity Value:administrative-fixture]]" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "target.user", + "log.o365InboxForwardingChange", + "log.o365MailboxForwardingSet", + "log.o365SendOnBehalfChange" + ] + }, + { + "name": "awareness_mailbox_client_access-missing-optional-identities", + "raw": "{\"Operation\":\"Set-CASMailbox\",\"Workload\":\"Exchange\",\"RecordType\":1,\"ResultStatus\":\"True\",\"Parameters\":[{\"Name\":\"Identity\",\"Value\":\"administrative-fixture\"}]}", + "rule": "office365/awareness_mailbox_client_access.yml", + "match": true, + "expected": { + "action": "Set-CASMailbox", + "log.Workload": "Exchange", + "log.RecordType": 1, + "log.ResultStatus": "True", + "actionResult": "success", + "log.Parameters": "[map[Name:Identity Value:administrative-fixture]]" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "origin.user", + "log.OrganizationId", + "log.ObjectId", + "target.user", + "log.o365InboxForwardingChange", + "log.o365MailboxForwardingSet", + "log.o365SendOnBehalfChange" + ] + }, + { + "name": "inbox-value-only-New-InboxRule", + "raw": "{\"Operation\":\"New-InboxRule\",\"Workload\":\"Exchange\",\"RecordType\":1,\"ResultStatus\":\"True\",\"UserId\":\"administrator@example.invalid\",\"ObjectId\":\"mailbox@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\",\"Parameters\":[{\"Name\":\"Name\",\"Value\":\"ForwardTo ForwardAsAttachmentTo RedirectTo\"}]}", + "rule": "office365/collection_microsoft_365_new_inbox_rule.yml", + "match": true, + "expected": { + "action": "New-InboxRule", + "log.Workload": "Exchange", + "log.RecordType": 1, + "origin.user": "administrator@example.invalid", + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "mailbox@example.invalid", + "log.ResultStatus": "True", + "actionResult": "success", + "log.Parameters": "[map[Name:Name Value:ForwardTo ForwardAsAttachmentTo RedirectTo]]" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "target.user", + "log.o365InboxForwardingChange", + "log.o365MailboxForwardingSet", + "log.o365SendOnBehalfChange" + ] + }, + { + "name": "inbox-no-parameters-New-InboxRule", + "raw": "{\"Operation\":\"New-InboxRule\",\"Workload\":\"Exchange\",\"RecordType\":1,\"ResultStatus\":\"True\",\"UserId\":\"administrator@example.invalid\",\"ObjectId\":\"mailbox@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\"}", + "rule": "office365/collection_microsoft_365_new_inbox_rule.yml", + "match": true, + "expected": { + "action": "New-InboxRule", + "log.Workload": "Exchange", + "log.RecordType": 1, + "origin.user": "administrator@example.invalid", + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "mailbox@example.invalid", + "log.ResultStatus": "True", + "actionResult": "success" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "target.user", + "log.Parameters", + "log.o365InboxForwardingChange", + "log.o365MailboxForwardingSet", + "log.o365SendOnBehalfChange" + ] + }, + { + "name": "inbox-prefix-parameter-New-InboxRule", + "raw": "{\"Operation\":\"New-InboxRule\",\"Workload\":\"Exchange\",\"RecordType\":1,\"ResultStatus\":\"True\",\"UserId\":\"administrator@example.invalid\",\"ObjectId\":\"mailbox@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\",\"Parameters\":[{\"Name\":\"ForwardToBackup\",\"Value\":\"delegate@example.invalid\"}]}", + "rule": "office365/collection_microsoft_365_new_inbox_rule.yml", + "match": true, + "expected": { + "action": "New-InboxRule", + "log.Workload": "Exchange", + "log.RecordType": 1, + "origin.user": "administrator@example.invalid", + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "mailbox@example.invalid", + "log.ResultStatus": "True", + "actionResult": "success", + "log.Parameters": "[map[Name:ForwardToBackup Value:delegate@example.invalid]]" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "target.user", + "log.o365InboxForwardingChange", + "log.o365MailboxForwardingSet", + "log.o365SendOnBehalfChange" + ] + }, + { + "name": "inbox-value-only-Set-InboxRule", + "raw": "{\"Operation\":\"Set-InboxRule\",\"Workload\":\"Exchange\",\"RecordType\":1,\"ResultStatus\":\"True\",\"UserId\":\"administrator@example.invalid\",\"ObjectId\":\"mailbox@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\",\"Parameters\":[{\"Name\":\"Name\",\"Value\":\"ForwardTo ForwardAsAttachmentTo RedirectTo\"}]}", + "rule": "office365/collection_microsoft_365_new_inbox_rule.yml", + "match": true, + "expected": { + "action": "Set-InboxRule", + "log.Workload": "Exchange", + "log.RecordType": 1, + "origin.user": "administrator@example.invalid", + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "mailbox@example.invalid", + "log.ResultStatus": "True", + "actionResult": "success", + "log.Parameters": "[map[Name:Name Value:ForwardTo ForwardAsAttachmentTo RedirectTo]]" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "target.user", + "log.o365InboxForwardingChange", + "log.o365MailboxForwardingSet", + "log.o365SendOnBehalfChange" + ] + }, + { + "name": "inbox-no-parameters-Set-InboxRule", + "raw": "{\"Operation\":\"Set-InboxRule\",\"Workload\":\"Exchange\",\"RecordType\":1,\"ResultStatus\":\"True\",\"UserId\":\"administrator@example.invalid\",\"ObjectId\":\"mailbox@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\"}", + "rule": "office365/collection_microsoft_365_new_inbox_rule.yml", + "match": true, + "expected": { + "action": "Set-InboxRule", + "log.Workload": "Exchange", + "log.RecordType": 1, + "origin.user": "administrator@example.invalid", + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "mailbox@example.invalid", + "log.ResultStatus": "True", + "actionResult": "success" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "target.user", + "log.Parameters", + "log.o365InboxForwardingChange", + "log.o365MailboxForwardingSet", + "log.o365SendOnBehalfChange" + ] + }, + { + "name": "inbox-prefix-parameter-Set-InboxRule", + "raw": "{\"Operation\":\"Set-InboxRule\",\"Workload\":\"Exchange\",\"RecordType\":1,\"ResultStatus\":\"True\",\"UserId\":\"administrator@example.invalid\",\"ObjectId\":\"mailbox@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\",\"Parameters\":[{\"Name\":\"ForwardToBackup\",\"Value\":\"delegate@example.invalid\"}]}", + "rule": "office365/collection_microsoft_365_new_inbox_rule.yml", + "match": true, + "expected": { + "action": "Set-InboxRule", + "log.Workload": "Exchange", + "log.RecordType": 1, + "origin.user": "administrator@example.invalid", + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "mailbox@example.invalid", + "log.ResultStatus": "True", + "actionResult": "success", + "log.Parameters": "[map[Name:ForwardToBackup Value:delegate@example.invalid]]" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "target.user", + "log.o365InboxForwardingChange", + "log.o365MailboxForwardingSet", + "log.o365SendOnBehalfChange" + ] + }, + { + "name": "mailbox-value-only-ForwardingAddress", + "raw": "{\"Operation\":\"Set-Mailbox\",\"Workload\":\"Exchange\",\"RecordType\":1,\"ResultStatus\":\"True\",\"UserId\":\"administrator@example.invalid\",\"ObjectId\":\"mailbox@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\",\"Parameters\":[{\"Name\":\"DisplayName\",\"Value\":\"ForwardingAddress\"}]}", + "rule": "office365/mailbox_auto_forwarding_set_mailbox.yml", + "match": false, + "expected": { + "action": "Set-Mailbox", + "log.Workload": "Exchange", + "log.RecordType": 1, + "origin.user": "administrator@example.invalid", + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "mailbox@example.invalid", + "log.ResultStatus": "True", + "actionResult": "success", + "log.Parameters": "[map[Name:DisplayName Value:ForwardingAddress]]" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "target.user", + "log.o365InboxForwardingChange", + "log.o365MailboxForwardingSet", + "log.o365SendOnBehalfChange" + ] + }, + { + "name": "mailbox-value-only-ForwardingSmtpAddress", + "raw": "{\"Operation\":\"Set-Mailbox\",\"Workload\":\"Exchange\",\"RecordType\":1,\"ResultStatus\":\"True\",\"UserId\":\"administrator@example.invalid\",\"ObjectId\":\"mailbox@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\",\"Parameters\":[{\"Name\":\"DisplayName\",\"Value\":\"ForwardingSmtpAddress\"}]}", + "rule": "office365/mailbox_auto_forwarding_set_mailbox.yml", + "match": false, + "expected": { + "action": "Set-Mailbox", + "log.Workload": "Exchange", + "log.RecordType": 1, + "origin.user": "administrator@example.invalid", + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "mailbox@example.invalid", + "log.ResultStatus": "True", + "actionResult": "success", + "log.Parameters": "[map[Name:DisplayName Value:ForwardingSmtpAddress]]" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "target.user", + "log.o365InboxForwardingChange", + "log.o365MailboxForwardingSet", + "log.o365SendOnBehalfChange" + ] + }, + { + "name": "mailbox-value-only-DeliverToMailboxAndForward", + "raw": "{\"Operation\":\"Set-Mailbox\",\"Workload\":\"Exchange\",\"RecordType\":1,\"ResultStatus\":\"True\",\"UserId\":\"administrator@example.invalid\",\"ObjectId\":\"mailbox@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\",\"Parameters\":[{\"Name\":\"DisplayName\",\"Value\":\"DeliverToMailboxAndForward\"}]}", + "rule": "office365/mailbox_auto_forwarding_set_mailbox.yml", + "match": false, + "expected": { + "action": "Set-Mailbox", + "log.Workload": "Exchange", + "log.RecordType": 1, + "origin.user": "administrator@example.invalid", + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "mailbox@example.invalid", + "log.ResultStatus": "True", + "actionResult": "success", + "log.Parameters": "[map[Name:DisplayName Value:DeliverToMailboxAndForward]]" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "target.user", + "log.o365InboxForwardingChange", + "log.o365MailboxForwardingSet", + "log.o365SendOnBehalfChange" + ] + }, + { + "name": "delegation-value-only", + "raw": "{\"Operation\":\"Set-Mailbox\",\"Workload\":\"Exchange\",\"RecordType\":1,\"ResultStatus\":\"True\",\"UserId\":\"administrator@example.invalid\",\"ObjectId\":\"mailbox@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\",\"Parameters\":[{\"Name\":\"DisplayName\",\"Value\":\"GrantSendOnBehalfTo\"}]}", + "rule": "office365/mailbox_delegation_abuse.yml", + "match": false, + "expected": { + "action": "Set-Mailbox", + "log.Workload": "Exchange", + "log.RecordType": 1, + "origin.user": "administrator@example.invalid", + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "mailbox@example.invalid", + "log.ResultStatus": "True", + "actionResult": "success", + "log.Parameters": "[map[Name:DisplayName Value:GrantSendOnBehalfTo]]" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "target.user", + "log.o365InboxForwardingChange", + "log.o365MailboxForwardingSet", + "log.o365SendOnBehalfChange" + ] + }, + { + "name": "mailbox-no-parameters", + "raw": "{\"Operation\":\"Set-Mailbox\",\"Workload\":\"Exchange\",\"RecordType\":1,\"ResultStatus\":\"True\",\"UserId\":\"administrator@example.invalid\",\"ObjectId\":\"mailbox@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\"}", + "rule": "office365/mailbox_auto_forwarding_set_mailbox.yml", + "match": false, + "expected": { + "action": "Set-Mailbox", + "log.Workload": "Exchange", + "log.RecordType": 1, + "origin.user": "administrator@example.invalid", + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "mailbox@example.invalid", + "log.ResultStatus": "True", + "actionResult": "success" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "target.user", + "log.Parameters", + "log.o365InboxForwardingChange", + "log.o365MailboxForwardingSet", + "log.o365SendOnBehalfChange" + ] + }, + { + "name": "mailbox-prefix-parameter", + "raw": "{\"Operation\":\"Set-Mailbox\",\"Workload\":\"Exchange\",\"RecordType\":1,\"ResultStatus\":\"True\",\"UserId\":\"administrator@example.invalid\",\"ObjectId\":\"mailbox@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\",\"Parameters\":[{\"Name\":\"ForwardingAddressBackup\",\"Value\":\"delegate@example.invalid\"}]}", + "rule": "office365/mailbox_auto_forwarding_set_mailbox.yml", + "match": false, + "expected": { + "action": "Set-Mailbox", + "log.Workload": "Exchange", + "log.RecordType": 1, + "origin.user": "administrator@example.invalid", + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "mailbox@example.invalid", + "log.ResultStatus": "True", + "actionResult": "success", + "log.Parameters": "[map[Name:ForwardingAddressBackup Value:delegate@example.invalid]]" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "target.user", + "log.o365InboxForwardingChange", + "log.o365MailboxForwardingSet", + "log.o365SendOnBehalfChange" + ] + }, + { + "name": "delegation-prefix-parameter", + "raw": "{\"Operation\":\"Set-Mailbox\",\"Workload\":\"Exchange\",\"RecordType\":1,\"ResultStatus\":\"True\",\"UserId\":\"administrator@example.invalid\",\"ObjectId\":\"mailbox@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\",\"Parameters\":[{\"Name\":\"GrantSendOnBehalfToBackup\",\"Value\":\"delegate@example.invalid\"}]}", + "rule": "office365/mailbox_delegation_abuse.yml", + "match": false, + "expected": { + "action": "Set-Mailbox", + "log.Workload": "Exchange", + "log.RecordType": 1, + "origin.user": "administrator@example.invalid", + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "mailbox@example.invalid", + "log.ResultStatus": "True", + "actionResult": "success", + "log.Parameters": "[map[Name:GrantSendOnBehalfToBackup Value:delegate@example.invalid]]" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "target.user", + "log.o365InboxForwardingChange", + "log.o365MailboxForwardingSet", + "log.o365SendOnBehalfChange" + ] + }, + { + "name": "json-string-parameters-ForwardTo", + "raw": "{\"Operation\":\"New-InboxRule\",\"Workload\":\"Exchange\",\"RecordType\":1,\"ResultStatus\":\"True\",\"UserId\":\"administrator@example.invalid\",\"ObjectId\":\"mailbox@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\",\"Parameters\":\"[{\\\"Name\\\":\\\"ForwardTo\\\",\\\"Value\\\":\\\"delegate@example.invalid\\\"}]\"}", + "rule": "office365/collection_microsoft_365_new_inbox_rule.yml", + "match": true, + "expected": { + "action": "New-InboxRule", + "log.Workload": "Exchange", + "log.RecordType": 1, + "origin.user": "administrator@example.invalid", + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "mailbox@example.invalid", + "log.ResultStatus": "True", + "actionResult": "success", + "log.Parameters": "[{\"Name\":\"ForwardTo\",\"Value\":\"delegate@example.invalid\"}]" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "target.user", + "log.o365InboxForwardingChange", + "log.o365MailboxForwardingSet", + "log.o365SendOnBehalfChange" + ] + }, + { + "name": "json-string-parameters-ForwardingSmtpAddress", + "raw": "{\"Operation\":\"Set-Mailbox\",\"Workload\":\"Exchange\",\"RecordType\":1,\"ResultStatus\":\"True\",\"UserId\":\"administrator@example.invalid\",\"ObjectId\":\"mailbox@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\",\"Parameters\":\"[{\\\"Name\\\":\\\"ForwardingSmtpAddress\\\",\\\"Value\\\":\\\"delegate@example.invalid\\\"}]\"}", + "rule": "office365/mailbox_auto_forwarding_set_mailbox.yml", + "match": false, + "expected": { + "action": "Set-Mailbox", + "log.Workload": "Exchange", + "log.RecordType": 1, + "origin.user": "administrator@example.invalid", + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "mailbox@example.invalid", + "log.ResultStatus": "True", + "actionResult": "success", + "log.Parameters": "[{\"Name\":\"ForwardingSmtpAddress\",\"Value\":\"delegate@example.invalid\"}]" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "target.user", + "log.o365InboxForwardingChange", + "log.o365MailboxForwardingSet", + "log.o365SendOnBehalfChange" + ] + }, + { + "name": "json-string-parameters-GrantSendOnBehalfTo", + "raw": "{\"Operation\":\"Set-Mailbox\",\"Workload\":\"Exchange\",\"RecordType\":1,\"ResultStatus\":\"True\",\"UserId\":\"administrator@example.invalid\",\"ObjectId\":\"mailbox@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\",\"Parameters\":\"[{\\\"Name\\\":\\\"GrantSendOnBehalfTo\\\",\\\"Value\\\":\\\"delegate@example.invalid\\\"}]\"}", + "rule": "office365/mailbox_delegation_abuse.yml", + "match": false, + "expected": { + "action": "Set-Mailbox", + "log.Workload": "Exchange", + "log.RecordType": 1, + "origin.user": "administrator@example.invalid", + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "mailbox@example.invalid", + "log.ResultStatus": "True", + "actionResult": "success", + "log.Parameters": "[{\"Name\":\"GrantSendOnBehalfTo\",\"Value\":\"delegate@example.invalid\"}]" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "target.user", + "log.o365InboxForwardingChange", + "log.o365MailboxForwardingSet", + "log.o365SendOnBehalfChange" + ] + }, + { + "name": "unrelated-exchange-operation", + "raw": "{\"Operation\":\"Get-Mailbox\",\"Workload\":\"Exchange\",\"RecordType\":1,\"ResultStatus\":\"True\",\"UserId\":\"administrator@example.invalid\",\"ObjectId\":\"mailbox@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\"}", + "rule": "office365/collection_microsoft_365_new_inbox_rule.yml", + "match": false, + "expected": { + "action": "Get-Mailbox", + "log.Workload": "Exchange", + "log.RecordType": 1, + "origin.user": "administrator@example.invalid", + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "mailbox@example.invalid", + "log.ResultStatus": "True", + "actionResult": "success" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "target.user", + "log.Parameters", + "log.o365InboxForwardingChange", + "log.o365MailboxForwardingSet", + "log.o365SendOnBehalfChange" + ] + }, + { + "name": "forward-missing-result", + "raw": "{\"Operation\":\"New-InboxRule\",\"Workload\":\"Exchange\",\"RecordType\":1,\"UserId\":\"administrator@example.invalid\",\"ObjectId\":\"mailbox@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\",\"Parameters\":[{\"Name\":\"ForwardTo\",\"Value\":\"delegate@example.invalid\"}]}", + "rule": "office365/mail_forwarding_rules.yml", + "match": false, + "expected": { + "action": "New-InboxRule", + "log.Workload": "Exchange", + "log.RecordType": 1, + "origin.user": "administrator@example.invalid", + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "mailbox@example.invalid", + "log.Parameters": "[map[Name:ForwardTo Value:delegate@example.invalid]]", + "log.o365InboxForwardingChange": "true" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "target.user", + "actionResult", + "log.ResultStatus", + "log.o365MailboxForwardingSet", + "log.o365SendOnBehalfChange" + ] + }, + { + "name": "spoofed-marker-inbox", + "raw": "{\"Operation\":\"New-InboxRule\",\"Workload\":\"Exchange\",\"RecordType\":1,\"ResultStatus\":\"True\",\"UserId\":\"administrator@example.invalid\",\"ObjectId\":\"mailbox@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\",\"Parameters\":[{\"Name\":\"DisplayName\",\"Value\":\"Unrelated setting\"}],\"o365InboxForwardingChange\":\"true\",\"o365MailboxForwardingSet\":\"true\",\"o365SendOnBehalfChange\":\"true\"}", + "rule": "office365/collection_microsoft_365_new_inbox_rule.yml", + "match": true, + "expected": { + "action": "New-InboxRule", + "log.Workload": "Exchange", + "log.RecordType": 1, + "origin.user": "administrator@example.invalid", + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "mailbox@example.invalid", + "log.ResultStatus": "True", + "actionResult": "success", + "log.Parameters": "[map[Name:DisplayName Value:Unrelated setting]]" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "target.user", + "log.o365InboxForwardingChange", + "log.o365MailboxForwardingSet", + "log.o365SendOnBehalfChange" + ] + }, + { + "name": "inbox-parameters-string-array", + "raw": "{\"Operation\":\"New-InboxRule\",\"Workload\":\"Exchange\",\"RecordType\":1,\"ResultStatus\":\"True\",\"UserId\":\"administrator@example.invalid\",\"ObjectId\":\"mailbox@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\",\"Parameters\":[\"ForwardTo\",\"ForwardingAddress\",\"GrantSendOnBehalfTo\"]}", + "rule": "office365/collection_microsoft_365_new_inbox_rule.yml", + "match": true, + "expected": { + "action": "New-InboxRule", + "log.Workload": "Exchange", + "log.RecordType": 1, + "origin.user": "administrator@example.invalid", + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "mailbox@example.invalid", + "log.ResultStatus": "True", + "actionResult": "success", + "log.Parameters": "[ForwardTo ForwardingAddress GrantSendOnBehalfTo]" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "target.user", + "log.o365InboxForwardingChange", + "log.o365MailboxForwardingSet", + "log.o365SendOnBehalfChange" + ] + }, + { + "name": "inbox-parameters-numeric-array", + "raw": "{\"Operation\":\"New-InboxRule\",\"Workload\":\"Exchange\",\"RecordType\":1,\"ResultStatus\":\"True\",\"UserId\":\"administrator@example.invalid\",\"ObjectId\":\"mailbox@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\",\"Parameters\":[1,2,3]}", + "rule": "office365/collection_microsoft_365_new_inbox_rule.yml", + "match": true, + "expected": { + "action": "New-InboxRule", + "log.Workload": "Exchange", + "log.RecordType": 1, + "origin.user": "administrator@example.invalid", + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "mailbox@example.invalid", + "log.ResultStatus": "True", + "actionResult": "success", + "log.Parameters": "[1 2 3]" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "target.user", + "log.o365InboxForwardingChange", + "log.o365MailboxForwardingSet", + "log.o365SendOnBehalfChange" + ] + }, + { + "name": "inbox-parameters-wrong-name-types", + "raw": "{\"Operation\":\"New-InboxRule\",\"Workload\":\"Exchange\",\"RecordType\":1,\"ResultStatus\":\"True\",\"UserId\":\"administrator@example.invalid\",\"ObjectId\":\"mailbox@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\",\"Parameters\":[{\"Name\":[\"ForwardTo\"],\"Value\":\"recipient@example.invalid\"},{\"Name\":{\"nested\":\"ForwardingAddress\"},\"Value\":\"recipient@example.invalid\"},{\"Name\":null,\"Value\":\"GrantSendOnBehalfTo\"}]}", + "rule": "office365/collection_microsoft_365_new_inbox_rule.yml", + "match": true, + "expected": { + "action": "New-InboxRule", + "log.Workload": "Exchange", + "log.RecordType": 1, + "origin.user": "administrator@example.invalid", + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "mailbox@example.invalid", + "log.ResultStatus": "True", + "actionResult": "success", + "log.Parameters": "[map[Name:[ForwardTo] Value:recipient@example.invalid] map[Name:map[nested:ForwardingAddress] Value:recipient@example.invalid] map[Name: Value:GrantSendOnBehalfTo]]" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "target.user", + "log.o365InboxForwardingChange", + "log.o365MailboxForwardingSet", + "log.o365SendOnBehalfChange" + ] + }, + { + "name": "inbox-parameters-object", + "raw": "{\"Operation\":\"New-InboxRule\",\"Workload\":\"Exchange\",\"RecordType\":1,\"ResultStatus\":\"True\",\"UserId\":\"administrator@example.invalid\",\"ObjectId\":\"mailbox@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\",\"Parameters\":{\"Name\":\"ForwardTo\",\"Value\":\"recipient@example.invalid\"}}", + "rule": "office365/collection_microsoft_365_new_inbox_rule.yml", + "match": true, + "expected": { + "action": "New-InboxRule", + "log.Workload": "Exchange", + "log.RecordType": 1, + "origin.user": "administrator@example.invalid", + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "mailbox@example.invalid", + "log.ResultStatus": "True", + "actionResult": "success", + "log.Parameters": "map[Name:ForwardTo Value:recipient@example.invalid]" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "target.user", + "log.o365InboxForwardingChange", + "log.o365MailboxForwardingSet", + "log.o365SendOnBehalfChange" + ] + }, + { + "name": "inbox-parameters-empty-array", + "raw": "{\"Operation\":\"New-InboxRule\",\"Workload\":\"Exchange\",\"RecordType\":1,\"ResultStatus\":\"True\",\"UserId\":\"administrator@example.invalid\",\"ObjectId\":\"mailbox@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\",\"Parameters\":[]}", + "rule": "office365/collection_microsoft_365_new_inbox_rule.yml", + "match": true, + "expected": { + "action": "New-InboxRule", + "log.Workload": "Exchange", + "log.RecordType": 1, + "origin.user": "administrator@example.invalid", + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "mailbox@example.invalid", + "log.ResultStatus": "True", + "actionResult": "success", + "log.Parameters": "[]" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "target.user", + "log.o365InboxForwardingChange", + "log.o365MailboxForwardingSet", + "log.o365SendOnBehalfChange" + ] + }, + { + "name": "inbox-parameters-null", + "raw": "{\"Operation\":\"New-InboxRule\",\"Workload\":\"Exchange\",\"RecordType\":1,\"ResultStatus\":\"True\",\"UserId\":\"administrator@example.invalid\",\"ObjectId\":\"mailbox@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\",\"Parameters\":null}", + "rule": "office365/collection_microsoft_365_new_inbox_rule.yml", + "match": true, + "expected": { + "action": "New-InboxRule", + "log.Workload": "Exchange", + "log.RecordType": 1, + "origin.user": "administrator@example.invalid", + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "mailbox@example.invalid", + "log.ResultStatus": "True", + "actionResult": "success", + "log.Parameters": "" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "target.user", + "log.o365InboxForwardingChange", + "log.o365MailboxForwardingSet", + "log.o365SendOnBehalfChange" + ] + }, + { + "name": "inbox-value-spoof-go-map", + "raw": "{\"Operation\":\"New-InboxRule\",\"Workload\":\"Exchange\",\"RecordType\":1,\"ResultStatus\":\"True\",\"UserId\":\"administrator@example.invalid\",\"ObjectId\":\"mailbox@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\",\"Parameters\":[{\"Name\":\"DisplayName\",\"Value\":\"map[Name:ForwardTo Value:recipient@example.invalid] map[Name:ForwardingAddress Value:recipient@example.invalid] map[Name:GrantSendOnBehalfTo Value:recipient@example.invalid]\"}]}", + "rule": "office365/collection_microsoft_365_new_inbox_rule.yml", + "match": true, + "expected": { + "action": "New-InboxRule", + "log.Workload": "Exchange", + "log.RecordType": 1, + "origin.user": "administrator@example.invalid", + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "mailbox@example.invalid", + "log.ResultStatus": "True", + "actionResult": "success", + "log.Parameters": "[map[Name:DisplayName Value:map[Name:ForwardTo Value:recipient@example.invalid] map[Name:ForwardingAddress Value:recipient@example.invalid] map[Name:GrantSendOnBehalfTo Value:recipient@example.invalid]]]" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "target.user", + "log.o365InboxForwardingChange", + "log.o365MailboxForwardingSet", + "log.o365SendOnBehalfChange" + ] + }, + { + "name": "inbox-value-spoof-json", + "raw": "{\"Operation\":\"New-InboxRule\",\"Workload\":\"Exchange\",\"RecordType\":1,\"ResultStatus\":\"True\",\"UserId\":\"administrator@example.invalid\",\"ObjectId\":\"mailbox@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\",\"Parameters\":[{\"Name\":\"DisplayName\",\"Value\":\"{\\\"Name\\\":\\\"ForwardTo\\\",\\\"Value\\\":\\\"recipient@example.invalid\\\"} {\\\"Name\\\":\\\"ForwardingAddress\\\",\\\"Value\\\":\\\"recipient@example.invalid\\\"} {\\\"Name\\\":\\\"GrantSendOnBehalfTo\\\",\\\"Value\\\":\\\"recipient@example.invalid\\\"}\"}]}", + "rule": "office365/collection_microsoft_365_new_inbox_rule.yml", + "match": true, + "expected": { + "action": "New-InboxRule", + "log.Workload": "Exchange", + "log.RecordType": 1, + "origin.user": "administrator@example.invalid", + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "mailbox@example.invalid", + "log.ResultStatus": "True", + "actionResult": "success", + "log.Parameters": "[map[Name:DisplayName Value:{\"Name\":\"ForwardTo\",\"Value\":\"recipient@example.invalid\"} {\"Name\":\"ForwardingAddress\",\"Value\":\"recipient@example.invalid\"} {\"Name\":\"GrantSendOnBehalfTo\",\"Value\":\"recipient@example.invalid\"}]]" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "target.user", + "log.o365InboxForwardingChange", + "log.o365MailboxForwardingSet", + "log.o365SendOnBehalfChange" + ] + }, + { + "name": "spoofed-marker-mailbox", + "raw": "{\"Operation\":\"Set-Mailbox\",\"Workload\":\"Exchange\",\"RecordType\":1,\"ResultStatus\":\"True\",\"UserId\":\"administrator@example.invalid\",\"ObjectId\":\"mailbox@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\",\"Parameters\":[{\"Name\":\"DisplayName\",\"Value\":\"Unrelated setting\"}],\"o365InboxForwardingChange\":\"true\",\"o365MailboxForwardingSet\":\"true\",\"o365SendOnBehalfChange\":\"true\"}", + "rule": "office365/mailbox_auto_forwarding_set_mailbox.yml", + "match": false, + "expected": { + "action": "Set-Mailbox", + "log.Workload": "Exchange", + "log.RecordType": 1, + "origin.user": "administrator@example.invalid", + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "mailbox@example.invalid", + "log.ResultStatus": "True", + "actionResult": "success", + "log.Parameters": "[map[Name:DisplayName Value:Unrelated setting]]" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "target.user", + "log.o365InboxForwardingChange", + "log.o365MailboxForwardingSet", + "log.o365SendOnBehalfChange" + ] + }, + { + "name": "mailbox-parameters-string-array", + "raw": "{\"Operation\":\"Set-Mailbox\",\"Workload\":\"Exchange\",\"RecordType\":1,\"ResultStatus\":\"True\",\"UserId\":\"administrator@example.invalid\",\"ObjectId\":\"mailbox@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\",\"Parameters\":[\"ForwardTo\",\"ForwardingAddress\",\"GrantSendOnBehalfTo\"]}", + "rule": "office365/mailbox_auto_forwarding_set_mailbox.yml", + "match": false, + "expected": { + "action": "Set-Mailbox", + "log.Workload": "Exchange", + "log.RecordType": 1, + "origin.user": "administrator@example.invalid", + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "mailbox@example.invalid", + "log.ResultStatus": "True", + "actionResult": "success", + "log.Parameters": "[ForwardTo ForwardingAddress GrantSendOnBehalfTo]" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "target.user", + "log.o365InboxForwardingChange", + "log.o365MailboxForwardingSet", + "log.o365SendOnBehalfChange" + ] + }, + { + "name": "mailbox-parameters-numeric-array", + "raw": "{\"Operation\":\"Set-Mailbox\",\"Workload\":\"Exchange\",\"RecordType\":1,\"ResultStatus\":\"True\",\"UserId\":\"administrator@example.invalid\",\"ObjectId\":\"mailbox@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\",\"Parameters\":[1,2,3]}", + "rule": "office365/mailbox_auto_forwarding_set_mailbox.yml", + "match": false, + "expected": { + "action": "Set-Mailbox", + "log.Workload": "Exchange", + "log.RecordType": 1, + "origin.user": "administrator@example.invalid", + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "mailbox@example.invalid", + "log.ResultStatus": "True", + "actionResult": "success", + "log.Parameters": "[1 2 3]" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "target.user", + "log.o365InboxForwardingChange", + "log.o365MailboxForwardingSet", + "log.o365SendOnBehalfChange" + ] + }, + { + "name": "mailbox-parameters-wrong-name-types", + "raw": "{\"Operation\":\"Set-Mailbox\",\"Workload\":\"Exchange\",\"RecordType\":1,\"ResultStatus\":\"True\",\"UserId\":\"administrator@example.invalid\",\"ObjectId\":\"mailbox@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\",\"Parameters\":[{\"Name\":[\"ForwardTo\"],\"Value\":\"recipient@example.invalid\"},{\"Name\":{\"nested\":\"ForwardingAddress\"},\"Value\":\"recipient@example.invalid\"},{\"Name\":null,\"Value\":\"GrantSendOnBehalfTo\"}]}", + "rule": "office365/mailbox_auto_forwarding_set_mailbox.yml", + "match": false, + "expected": { + "action": "Set-Mailbox", + "log.Workload": "Exchange", + "log.RecordType": 1, + "origin.user": "administrator@example.invalid", + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "mailbox@example.invalid", + "log.ResultStatus": "True", + "actionResult": "success", + "log.Parameters": "[map[Name:[ForwardTo] Value:recipient@example.invalid] map[Name:map[nested:ForwardingAddress] Value:recipient@example.invalid] map[Name: Value:GrantSendOnBehalfTo]]" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "target.user", + "log.o365InboxForwardingChange", + "log.o365MailboxForwardingSet", + "log.o365SendOnBehalfChange" + ] + }, + { + "name": "mailbox-parameters-object", + "raw": "{\"Operation\":\"Set-Mailbox\",\"Workload\":\"Exchange\",\"RecordType\":1,\"ResultStatus\":\"True\",\"UserId\":\"administrator@example.invalid\",\"ObjectId\":\"mailbox@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\",\"Parameters\":{\"Name\":\"ForwardTo\",\"Value\":\"recipient@example.invalid\"}}", + "rule": "office365/mailbox_auto_forwarding_set_mailbox.yml", + "match": false, + "expected": { + "action": "Set-Mailbox", + "log.Workload": "Exchange", + "log.RecordType": 1, + "origin.user": "administrator@example.invalid", + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "mailbox@example.invalid", + "log.ResultStatus": "True", + "actionResult": "success", + "log.Parameters": "map[Name:ForwardTo Value:recipient@example.invalid]" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "target.user", + "log.o365InboxForwardingChange", + "log.o365MailboxForwardingSet", + "log.o365SendOnBehalfChange" + ] + }, + { + "name": "mailbox-parameters-empty-array", + "raw": "{\"Operation\":\"Set-Mailbox\",\"Workload\":\"Exchange\",\"RecordType\":1,\"ResultStatus\":\"True\",\"UserId\":\"administrator@example.invalid\",\"ObjectId\":\"mailbox@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\",\"Parameters\":[]}", + "rule": "office365/mailbox_auto_forwarding_set_mailbox.yml", + "match": false, + "expected": { + "action": "Set-Mailbox", + "log.Workload": "Exchange", + "log.RecordType": 1, + "origin.user": "administrator@example.invalid", + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "mailbox@example.invalid", + "log.ResultStatus": "True", + "actionResult": "success", + "log.Parameters": "[]" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "target.user", + "log.o365InboxForwardingChange", + "log.o365MailboxForwardingSet", + "log.o365SendOnBehalfChange" + ] + }, + { + "name": "mailbox-parameters-null", + "raw": "{\"Operation\":\"Set-Mailbox\",\"Workload\":\"Exchange\",\"RecordType\":1,\"ResultStatus\":\"True\",\"UserId\":\"administrator@example.invalid\",\"ObjectId\":\"mailbox@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\",\"Parameters\":null}", + "rule": "office365/mailbox_auto_forwarding_set_mailbox.yml", + "match": false, + "expected": { + "action": "Set-Mailbox", + "log.Workload": "Exchange", + "log.RecordType": 1, + "origin.user": "administrator@example.invalid", + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "mailbox@example.invalid", + "log.ResultStatus": "True", + "actionResult": "success", + "log.Parameters": "" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "target.user", + "log.o365InboxForwardingChange", + "log.o365MailboxForwardingSet", + "log.o365SendOnBehalfChange" + ] + }, + { + "name": "mailbox-value-spoof-go-map", + "raw": "{\"Operation\":\"Set-Mailbox\",\"Workload\":\"Exchange\",\"RecordType\":1,\"ResultStatus\":\"True\",\"UserId\":\"administrator@example.invalid\",\"ObjectId\":\"mailbox@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\",\"Parameters\":[{\"Name\":\"DisplayName\",\"Value\":\"map[Name:ForwardTo Value:recipient@example.invalid] map[Name:ForwardingAddress Value:recipient@example.invalid] map[Name:GrantSendOnBehalfTo Value:recipient@example.invalid]\"}]}", + "rule": "office365/mailbox_auto_forwarding_set_mailbox.yml", + "match": false, + "expected": { + "action": "Set-Mailbox", + "log.Workload": "Exchange", + "log.RecordType": 1, + "origin.user": "administrator@example.invalid", + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "mailbox@example.invalid", + "log.ResultStatus": "True", + "actionResult": "success", + "log.Parameters": "[map[Name:DisplayName Value:map[Name:ForwardTo Value:recipient@example.invalid] map[Name:ForwardingAddress Value:recipient@example.invalid] map[Name:GrantSendOnBehalfTo Value:recipient@example.invalid]]]" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "target.user", + "log.o365InboxForwardingChange", + "log.o365MailboxForwardingSet", + "log.o365SendOnBehalfChange" + ] + }, + { + "name": "mailbox-value-spoof-json", + "raw": "{\"Operation\":\"Set-Mailbox\",\"Workload\":\"Exchange\",\"RecordType\":1,\"ResultStatus\":\"True\",\"UserId\":\"administrator@example.invalid\",\"ObjectId\":\"mailbox@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\",\"Parameters\":[{\"Name\":\"DisplayName\",\"Value\":\"{\\\"Name\\\":\\\"ForwardTo\\\",\\\"Value\\\":\\\"recipient@example.invalid\\\"} {\\\"Name\\\":\\\"ForwardingAddress\\\",\\\"Value\\\":\\\"recipient@example.invalid\\\"} {\\\"Name\\\":\\\"GrantSendOnBehalfTo\\\",\\\"Value\\\":\\\"recipient@example.invalid\\\"}\"}]}", + "rule": "office365/mailbox_auto_forwarding_set_mailbox.yml", + "match": false, + "expected": { + "action": "Set-Mailbox", + "log.Workload": "Exchange", + "log.RecordType": 1, + "origin.user": "administrator@example.invalid", + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "mailbox@example.invalid", + "log.ResultStatus": "True", + "actionResult": "success", + "log.Parameters": "[map[Name:DisplayName Value:{\"Name\":\"ForwardTo\",\"Value\":\"recipient@example.invalid\"} {\"Name\":\"ForwardingAddress\",\"Value\":\"recipient@example.invalid\"} {\"Name\":\"GrantSendOnBehalfTo\",\"Value\":\"recipient@example.invalid\"}]]" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "target.user", + "log.o365InboxForwardingChange", + "log.o365MailboxForwardingSet", + "log.o365SendOnBehalfChange" + ] + }, + { + "name": "spoofed-marker-delegation", + "raw": "{\"Operation\":\"Set-Mailbox\",\"Workload\":\"Exchange\",\"RecordType\":1,\"ResultStatus\":\"True\",\"UserId\":\"administrator@example.invalid\",\"ObjectId\":\"mailbox@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\",\"Parameters\":[{\"Name\":\"DisplayName\",\"Value\":\"Unrelated setting\"}],\"o365InboxForwardingChange\":\"true\",\"o365MailboxForwardingSet\":\"true\",\"o365SendOnBehalfChange\":\"true\"}", + "rule": "office365/mailbox_delegation_abuse.yml", + "match": false, + "expected": { + "action": "Set-Mailbox", + "log.Workload": "Exchange", + "log.RecordType": 1, + "origin.user": "administrator@example.invalid", + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "mailbox@example.invalid", + "log.ResultStatus": "True", + "actionResult": "success", + "log.Parameters": "[map[Name:DisplayName Value:Unrelated setting]]" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "target.user", + "log.o365InboxForwardingChange", + "log.o365MailboxForwardingSet", + "log.o365SendOnBehalfChange" + ] + }, + { + "name": "delegation-parameters-string-array", + "raw": "{\"Operation\":\"Set-Mailbox\",\"Workload\":\"Exchange\",\"RecordType\":1,\"ResultStatus\":\"True\",\"UserId\":\"administrator@example.invalid\",\"ObjectId\":\"mailbox@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\",\"Parameters\":[\"ForwardTo\",\"ForwardingAddress\",\"GrantSendOnBehalfTo\"]}", + "rule": "office365/mailbox_delegation_abuse.yml", + "match": false, + "expected": { + "action": "Set-Mailbox", + "log.Workload": "Exchange", + "log.RecordType": 1, + "origin.user": "administrator@example.invalid", + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "mailbox@example.invalid", + "log.ResultStatus": "True", + "actionResult": "success", + "log.Parameters": "[ForwardTo ForwardingAddress GrantSendOnBehalfTo]" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "target.user", + "log.o365InboxForwardingChange", + "log.o365MailboxForwardingSet", + "log.o365SendOnBehalfChange" + ] + }, + { + "name": "delegation-parameters-numeric-array", + "raw": "{\"Operation\":\"Set-Mailbox\",\"Workload\":\"Exchange\",\"RecordType\":1,\"ResultStatus\":\"True\",\"UserId\":\"administrator@example.invalid\",\"ObjectId\":\"mailbox@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\",\"Parameters\":[1,2,3]}", + "rule": "office365/mailbox_delegation_abuse.yml", + "match": false, + "expected": { + "action": "Set-Mailbox", + "log.Workload": "Exchange", + "log.RecordType": 1, + "origin.user": "administrator@example.invalid", + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "mailbox@example.invalid", + "log.ResultStatus": "True", + "actionResult": "success", + "log.Parameters": "[1 2 3]" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "target.user", + "log.o365InboxForwardingChange", + "log.o365MailboxForwardingSet", + "log.o365SendOnBehalfChange" + ] + }, + { + "name": "delegation-parameters-wrong-name-types", + "raw": "{\"Operation\":\"Set-Mailbox\",\"Workload\":\"Exchange\",\"RecordType\":1,\"ResultStatus\":\"True\",\"UserId\":\"administrator@example.invalid\",\"ObjectId\":\"mailbox@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\",\"Parameters\":[{\"Name\":[\"ForwardTo\"],\"Value\":\"recipient@example.invalid\"},{\"Name\":{\"nested\":\"ForwardingAddress\"},\"Value\":\"recipient@example.invalid\"},{\"Name\":null,\"Value\":\"GrantSendOnBehalfTo\"}]}", + "rule": "office365/mailbox_delegation_abuse.yml", + "match": false, + "expected": { + "action": "Set-Mailbox", + "log.Workload": "Exchange", + "log.RecordType": 1, + "origin.user": "administrator@example.invalid", + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "mailbox@example.invalid", + "log.ResultStatus": "True", + "actionResult": "success", + "log.Parameters": "[map[Name:[ForwardTo] Value:recipient@example.invalid] map[Name:map[nested:ForwardingAddress] Value:recipient@example.invalid] map[Name: Value:GrantSendOnBehalfTo]]" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "target.user", + "log.o365InboxForwardingChange", + "log.o365MailboxForwardingSet", + "log.o365SendOnBehalfChange" + ] + }, + { + "name": "delegation-parameters-object", + "raw": "{\"Operation\":\"Set-Mailbox\",\"Workload\":\"Exchange\",\"RecordType\":1,\"ResultStatus\":\"True\",\"UserId\":\"administrator@example.invalid\",\"ObjectId\":\"mailbox@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\",\"Parameters\":{\"Name\":\"ForwardTo\",\"Value\":\"recipient@example.invalid\"}}", + "rule": "office365/mailbox_delegation_abuse.yml", + "match": false, + "expected": { + "action": "Set-Mailbox", + "log.Workload": "Exchange", + "log.RecordType": 1, + "origin.user": "administrator@example.invalid", + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "mailbox@example.invalid", + "log.ResultStatus": "True", + "actionResult": "success", + "log.Parameters": "map[Name:ForwardTo Value:recipient@example.invalid]" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "target.user", + "log.o365InboxForwardingChange", + "log.o365MailboxForwardingSet", + "log.o365SendOnBehalfChange" + ] + }, + { + "name": "delegation-parameters-empty-array", + "raw": "{\"Operation\":\"Set-Mailbox\",\"Workload\":\"Exchange\",\"RecordType\":1,\"ResultStatus\":\"True\",\"UserId\":\"administrator@example.invalid\",\"ObjectId\":\"mailbox@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\",\"Parameters\":[]}", + "rule": "office365/mailbox_delegation_abuse.yml", + "match": false, + "expected": { + "action": "Set-Mailbox", + "log.Workload": "Exchange", + "log.RecordType": 1, + "origin.user": "administrator@example.invalid", + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "mailbox@example.invalid", + "log.ResultStatus": "True", + "actionResult": "success", + "log.Parameters": "[]" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "target.user", + "log.o365InboxForwardingChange", + "log.o365MailboxForwardingSet", + "log.o365SendOnBehalfChange" + ] + }, + { + "name": "delegation-parameters-null", + "raw": "{\"Operation\":\"Set-Mailbox\",\"Workload\":\"Exchange\",\"RecordType\":1,\"ResultStatus\":\"True\",\"UserId\":\"administrator@example.invalid\",\"ObjectId\":\"mailbox@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\",\"Parameters\":null}", + "rule": "office365/mailbox_delegation_abuse.yml", + "match": false, + "expected": { + "action": "Set-Mailbox", + "log.Workload": "Exchange", + "log.RecordType": 1, + "origin.user": "administrator@example.invalid", + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "mailbox@example.invalid", + "log.ResultStatus": "True", + "actionResult": "success", + "log.Parameters": "" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "target.user", + "log.o365InboxForwardingChange", + "log.o365MailboxForwardingSet", + "log.o365SendOnBehalfChange" + ] + }, + { + "name": "delegation-value-spoof-go-map", + "raw": "{\"Operation\":\"Set-Mailbox\",\"Workload\":\"Exchange\",\"RecordType\":1,\"ResultStatus\":\"True\",\"UserId\":\"administrator@example.invalid\",\"ObjectId\":\"mailbox@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\",\"Parameters\":[{\"Name\":\"DisplayName\",\"Value\":\"map[Name:ForwardTo Value:recipient@example.invalid] map[Name:ForwardingAddress Value:recipient@example.invalid] map[Name:GrantSendOnBehalfTo Value:recipient@example.invalid]\"}]}", + "rule": "office365/mailbox_delegation_abuse.yml", + "match": false, + "expected": { + "action": "Set-Mailbox", + "log.Workload": "Exchange", + "log.RecordType": 1, + "origin.user": "administrator@example.invalid", + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "mailbox@example.invalid", + "log.ResultStatus": "True", + "actionResult": "success", + "log.Parameters": "[map[Name:DisplayName Value:map[Name:ForwardTo Value:recipient@example.invalid] map[Name:ForwardingAddress Value:recipient@example.invalid] map[Name:GrantSendOnBehalfTo Value:recipient@example.invalid]]]" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "target.user", + "log.o365InboxForwardingChange", + "log.o365MailboxForwardingSet", + "log.o365SendOnBehalfChange" + ] + }, + { + "name": "delegation-value-spoof-json", + "raw": "{\"Operation\":\"Set-Mailbox\",\"Workload\":\"Exchange\",\"RecordType\":1,\"ResultStatus\":\"True\",\"UserId\":\"administrator@example.invalid\",\"ObjectId\":\"mailbox@example.invalid\",\"OrganizationId\":\"11111111-1111-4111-8111-111111111111\",\"Parameters\":[{\"Name\":\"DisplayName\",\"Value\":\"{\\\"Name\\\":\\\"ForwardTo\\\",\\\"Value\\\":\\\"recipient@example.invalid\\\"} {\\\"Name\\\":\\\"ForwardingAddress\\\",\\\"Value\\\":\\\"recipient@example.invalid\\\"} {\\\"Name\\\":\\\"GrantSendOnBehalfTo\\\",\\\"Value\\\":\\\"recipient@example.invalid\\\"}\"}]}", + "rule": "office365/mailbox_delegation_abuse.yml", + "match": false, + "expected": { + "action": "Set-Mailbox", + "log.Workload": "Exchange", + "log.RecordType": 1, + "origin.user": "administrator@example.invalid", + "log.OrganizationId": "11111111-1111-4111-8111-111111111111", + "log.ObjectId": "mailbox@example.invalid", + "log.ResultStatus": "True", + "actionResult": "success", + "log.Parameters": "[map[Name:DisplayName Value:{\"Name\":\"ForwardTo\",\"Value\":\"recipient@example.invalid\"} {\"Name\":\"ForwardingAddress\",\"Value\":\"recipient@example.invalid\"} {\"Name\":\"GrantSendOnBehalfTo\",\"Value\":\"recipient@example.invalid\"}]]" + }, + "absent": [ + "log.Operation", + "log.UserId", + "origin.ip", + "target.user", + "log.o365InboxForwardingChange", + "log.o365MailboxForwardingSet", + "log.o365SendOnBehalfChange" + ] + } +] diff --git a/rules/office365/awareness_calendar_delegation.yml b/rules/office365/awareness_calendar_delegation.yml new file mode 100644 index 000000000..29a9a1f09 --- /dev/null +++ b/rules/office365/awareness_calendar_delegation.yml @@ -0,0 +1,27 @@ +# Rule version v1.1.2 + +dataTypes: +- o365 +name: Office 365 Calendar Delegate Changed +description: | + A user was added to or removed from another mailbox owner’s calendar delegation. The operation can be routine scheduling administration, but changes who can manage calendar items. + + Review the actor, affected object, change request and authorized owner. This alert reports an audited configuration change; it does not by itself establish compromise, an external recipient, or a currently enabled setting. +category: Administrative Awareness +technique: 'T1098.002 - Account Manipulation: Additional Email Delegate Permissions' +adversary: origin +impact: + confidentiality: 1 + integrity: 1 + availability: 0 +references: +- https://learn.microsoft.com/en-us/purview/audit-log-activities +- https://learn.microsoft.com/en-us/office/office-365-management-api/office-365-management-activity-api-schema +where: | + equals("log.Workload", "Exchange") && equals("actionResult", "success") && equals("action", "UpdateCalendarDelegation") +groupBy: +- lastEvent.tenantId +- lastEvent.log.OrganizationId +- dataSource +- adversary.user +- lastEvent.action diff --git a/rules/office365/awareness_mail_connectors.yml b/rules/office365/awareness_mail_connectors.yml new file mode 100644 index 000000000..5f692cc9c --- /dev/null +++ b/rules/office365/awareness_mail_connectors.yml @@ -0,0 +1,28 @@ +# Rule version v1.1.2 + +dataTypes: +- o365 +name: Office 365 Mail Connector Changed +description: | + An inbound or outbound Exchange Online mail connector was created, changed or removed. Review routing and authentication settings in the audited object and confirm the administrator intended the change. + + Review the actor, affected object, change request and authorized owner. This alert reports an audited configuration change; it does not by itself establish compromise, an external recipient, or a currently enabled setting. +category: Administrative Awareness +technique: T1537 - Transfer Data to Cloud Account +adversary: origin +impact: + confidentiality: 1 + integrity: 1 + availability: 0 +references: +- https://learn.microsoft.com/en-us/purview/audit-log-activities +- https://learn.microsoft.com/en-us/office/office-365-management-api/office-365-management-activity-api-schema +- https://learn.microsoft.com/en-us/powershell/module/exchangepowershell/new-inboundconnector?view=exchange-ps +where: | + equals("log.Workload", "Exchange") && equals("actionResult", "success") && oneOf("action", ["New-InboundConnector", "Set-InboundConnector", "Remove-InboundConnector", "New-OutboundConnector", "Set-OutboundConnector", "Remove-OutboundConnector"]) +groupBy: +- lastEvent.tenantId +- lastEvent.log.OrganizationId +- dataSource +- adversary.user +- lastEvent.action diff --git a/rules/office365/awareness_mailbox_client_access.yml b/rules/office365/awareness_mailbox_client_access.yml new file mode 100644 index 000000000..23015c1ad --- /dev/null +++ b/rules/office365/awareness_mailbox_client_access.yml @@ -0,0 +1,28 @@ +# Rule version v1.1.2 + +dataTypes: +- o365 +name: Office 365 Mailbox Client Access Changed +description: | + An administrator changed client access settings on a mailbox with Set-CASMailbox. Examine the changed protocol or access setting and the affected mailbox before deciding whether follow-up is needed. + + Review the actor, affected object, change request and authorized owner. This alert reports an audited configuration change; it does not by itself establish compromise, an external recipient, or a currently enabled setting. +category: Administrative Awareness +technique: 'T1114.002 - Email Collection: Remote Email Collection' +adversary: origin +impact: + confidentiality: 1 + integrity: 1 + availability: 0 +references: +- https://learn.microsoft.com/en-us/purview/audit-log-activities +- https://learn.microsoft.com/en-us/office/office-365-management-api/office-365-management-activity-api-schema +- https://learn.microsoft.com/en-us/powershell/module/exchangepowershell/set-casmailbox?view=exchange-ps +where: | + equals("log.Workload", "Exchange") && equals("actionResult", "success") && equals("action", "Set-CASMailbox") +groupBy: +- lastEvent.tenantId +- lastEvent.log.OrganizationId +- dataSource +- adversary.user +- lastEvent.action diff --git a/rules/office365/awareness_mailbox_folder_permissions.yml b/rules/office365/awareness_mailbox_folder_permissions.yml new file mode 100644 index 000000000..4fa86b90e --- /dev/null +++ b/rules/office365/awareness_mailbox_folder_permissions.yml @@ -0,0 +1,33 @@ +# Rule version v1.1.2 + +dataTypes: +- o365 +name: Office 365 Mailbox Folder Permission Changed +description: | + A folder permission on someone else's mailbox was added, modified or removed, either with an Exchange administrator cmdlet or through an audited mailbox client. This can grant or revoke access to the messages in that folder. + + Changes owners make to their own mailbox, such as sharing a calendar, do not raise this alert; the audit record shows them with logon type Owner or with the mailbox owner as the actor. Neither do changes made by Microsoft service accounts, which the audit record marks with ExternalAccess set to true and a Windows security identifier (S-1-5-...) as the actor, for example when Microsoft 365 configures group mailboxes. + + Review the actor, affected object, change request and authorized owner. This alert reports an audited configuration change; it does not by itself establish compromise, an external recipient, or a currently enabled setting. +category: Administrative Awareness +technique: 'T1098.002 - Account Manipulation: Additional Email Delegate Permissions' +adversary: origin +impact: + confidentiality: 1 + integrity: 1 + availability: 0 +references: +- https://learn.microsoft.com/en-us/purview/audit-log-activities +- https://learn.microsoft.com/en-us/office/office-365-management-api/office-365-management-activity-api-schema +- https://learn.microsoft.com/en-us/powershell/module/exchangepowershell/add-mailboxfolderpermission?view=exchange-ps +where: | + equals("log.Workload", "Exchange") && equals("actionResult", "success") && oneOf("action", ["Add-MailboxFolderPermission", "Set-MailboxFolderPermission", "Remove-MailboxFolderPermission", "AddFolderPermissions", "ModifyFolderPermissions", "RemoveFolderPermissions"]) && + !equals("log.LogonType", 0) && + (!exists("target.user") || safe("origin.user", "") != safe("target.user", "")) && + !(equals("log.ExternalAccess", true) && startsWith("origin.user", "S-1-5-")) +groupBy: +- lastEvent.tenantId +- lastEvent.log.OrganizationId +- dataSource +- adversary.user +- lastEvent.action diff --git a/rules/office365/collection_microsoft_365_new_inbox_rule.yml b/rules/office365/collection_microsoft_365_new_inbox_rule.yml index 839453243..4109598d7 100644 --- a/rules/office365/collection_microsoft_365_new_inbox_rule.yml +++ b/rules/office365/collection_microsoft_365_new_inbox_rule.yml @@ -1,26 +1,30 @@ -# Rule version v1.0.3 +# Rule version v1.1.2 dataTypes: - - "o365" -name: "Microsoft 365 New Inbox Rule Created" -impact: - confidentiality: 3 - integrity: 2 - availability: 1 -category: "Collection" -technique: "T1114 - Email Collection" +- o365 +name: Office 365 Inbox Rule Changed +description: | + A user or administrator created, changed, enabled, disabled or removed an inbox rule with an Exchange command, for example from Outlook on the web or PowerShell. Rules that move or delete mail can hide messages from the mailbox owner. New and modified rules with forwarding settings raise the separate forwarding alert instead. + + Outlook desktop records its rule saves as UpdateInboxRules and writes them repeatedly for the same rules, usually without any rule change, so those records do not raise this alert. + + Review the actor, affected object, change request and authorized owner. This alert reports an audited configuration change; it does not by itself establish compromise, an external recipient, or a currently enabled setting. +category: Administrative Awareness +technique: 'T1564.008 - Hide Artifacts: Email Hiding Rules' adversary: origin -description: "Credential Access consists of techniques for stealing credentials like account names and passwords. Techniques used to get credentials include keylogging or credential dumping. Using legitimate credentials can give adversaries access to systems, make them harder to detect, and provide the opportunity to create more accounts to help achieve their goals.
- Identifies when a new Inbox rule is created in Microsoft 365. Inbox rules process messages in the Inbox based on conditions and take actions, such as moving a message to a specified folder or deleting a message. Adequate permissions are required on the mailbox to create an Inbox rule." +impact: + confidentiality: 1 + integrity: 1 + availability: 0 references: - - "https://docs.microsoft.com/en-us/microsoft-365/security/office-365-security/responding-to-a-compromised-email-account?view=o365-worldwide" - - "https://docs.microsoft.com/en-us/powershell/module/exchange/new-inboxrule?view=exchange-ps" - - "https://docs.microsoft.com/en-us/microsoft-365/security/office-365-security/detect-and-remediate-outlook-rules-forms-attack?view=o365-worldwide" - - "https://attack.mitre.org/techniques/T1114/" - - "https://attack.mitre.org/techniques/T1114/003/" - - "https://attack.mitre.org/tactics/TA0009/" +- https://learn.microsoft.com/en-us/purview/audit-log-activities +- https://learn.microsoft.com/en-us/office/office-365-management-api/office-365-management-activity-api-schema +- https://learn.microsoft.com/en-us/powershell/module/exchangepowershell/new-inboxrule?view=exchange-ps where: | - equals("log.Workload", "Exchange") && equals("action", "New-InboxRule") && oneOf("actionResult", ["success"]) + equals("log.Workload", "Exchange") && equals("actionResult", "success") && oneOf("action", ["New-InboxRule", "Set-InboxRule", "Enable-InboxRule", "Disable-InboxRule", "Remove-InboxRule"]) && !(oneOf("action", ["New-InboxRule", "Set-InboxRule"]) && (equals("log.o365InboxForwardingChange", "true") || exists("log.Parameters.#(Name==ForwardTo).Name") || exists("log.Parameters.#(Name==ForwardAsAttachmentTo).Name") || exists("log.Parameters.#(Name==RedirectTo).Name"))) groupBy: - - adversary.ip - - adversary.user +- lastEvent.tenantId +- lastEvent.log.OrganizationId +- dataSource +- adversary.user +- lastEvent.action diff --git a/rules/office365/credential_access_microsoft_365_potential_password_spraying_attack.yml b/rules/office365/credential_access_microsoft_365_potential_password_spraying_attack.yml index 3e8e7f493..8a118b931 100644 --- a/rules/office365/credential_access_microsoft_365_potential_password_spraying_attack.yml +++ b/rules/office365/credential_access_microsoft_365_potential_password_spraying_attack.yml @@ -1,4 +1,4 @@ -# Rule version v1.0.3 +# Rule version v1.0.5 dataTypes: - "o365" @@ -16,7 +16,7 @@ references: description: "Credential Access consists of techniques for stealing credentials like account names and passwords. Techniques used to get credentials include keylogging or credential dumping. Using legitimate credentials can give adversaries access to systems, make them harder to detect, and provide the opportunity to create more accounts to help achieve their goals.
Identifies a high number (25) of failed Microsoft 365 user authentication attempts from a single IP address within 30 minutes, which could be indicative of a password spraying attack. An adversary may attempt a password spraying attack to obtain unauthorized access to user accounts." where: | - oneOf("log.Workload", ["Exchange", "AzureActiveDirectory"]) && oneOf("action", ["UserLoginFailed", "PasswordLogonInitialAuthUsingPassword"]) && oneOf("actionResult", ["failed"]) && exists("origin.ip") + oneOf("log.Workload", ["Exchange", "AzureActiveDirectory"]) && oneOf("action", ["UserLoginFailed", "PasswordLogonInitialAuthUsingPassword"]) && oneOf("actionResult", ["failure", "failed"]) && exists("origin.ip") afterEvents: - indexPattern: v11-log-o365-* with: @@ -27,4 +27,3 @@ afterEvents: count: 5 groupBy: - adversary.ip - - adversary.user diff --git a/rules/office365/dlp_policy_violations.yml b/rules/office365/dlp_policy_violations.yml index c6ec30033..1047e6457 100644 --- a/rules/office365/dlp_policy_violations.yml +++ b/rules/office365/dlp_policy_violations.yml @@ -1,4 +1,4 @@ -# Rule version v1.0.0 +# Rule version v1.0.1 dataTypes: - o365 @@ -41,7 +41,7 @@ where: | equals("log.Workload", "Teams") || equals("log.Workload", "SecurityComplianceCenter") ) && - !equals("actionResult", "failed") + !oneOf("actionResult", ["failure", "failed"]) groupBy: - lastEvent.log.PolicyId - lastEvent.log.SensitiveInfoTypeData diff --git a/rules/office365/information_barriers_violations.yml b/rules/office365/information_barriers_violations.yml index ef3b66437..2301d1c36 100644 --- a/rules/office365/information_barriers_violations.yml +++ b/rules/office365/information_barriers_violations.yml @@ -1,4 +1,4 @@ -# Rule version v1.0.0 +# Rule version v1.0.1 dataTypes: - o365 @@ -24,7 +24,7 @@ description: | 5. Provide additional training to users if violations appear to be due to lack of awareness 6. Consider implementing additional technical controls to prevent future violations where: | - equals("action", "InformationBarrierPolicyViolation") || (equals("log.PolicyType", "InformationBarrier") && equals("actionResult", "blocked")) || (equals("log.ViolationType", "InformationBarrier") && equals("action", "CommunicationBlocked")) + equals("action", "InformationBarrierPolicyViolation") || (equals("log.PolicyType", "InformationBarrier") && oneOf("actionResult", ["denied", "blocked"])) || (equals("log.ViolationType", "InformationBarrier") && equals("action", "CommunicationBlocked")) afterEvents: - indexPattern: v11-log-o365-* with: diff --git a/rules/office365/insider_risk_indicators.yml b/rules/office365/insider_risk_indicators.yml index 608a7f5c2..fbacd7aec 100644 --- a/rules/office365/insider_risk_indicators.yml +++ b/rules/office365/insider_risk_indicators.yml @@ -1,4 +1,4 @@ -# Rule version v1.0.0 +# Rule version v1.0.1 dataTypes: - o365 @@ -26,7 +26,7 @@ description: | 7. Consider implementing additional monitoring or access restrictions if suspicious activity is confirmed 8. Escalate to security team and HR if malicious intent is suspected where: | - equals("action", "InsiderRiskAlert") || (contains("log.PolicyName", "InsiderRisk") && equals("actionResult", "blocked")) || (oneOf("log.RiskLevel", ["High", "Critical"]) && equals("log.AlertSource", "InsiderRiskManagement")) + equals("action", "InsiderRiskAlert") || (contains("log.PolicyName", "InsiderRisk") && oneOf("actionResult", ["denied", "blocked"])) || (oneOf("log.RiskLevel", ["High", "Critical"]) && equals("log.AlertSource", "InsiderRiskManagement")) groupBy: - lastEvent.log.PolicyName - lastEvent.log.RiskLevel diff --git a/rules/office365/mail_forwarding_rules.yml b/rules/office365/mail_forwarding_rules.yml index 13c797862..c3af390b9 100644 --- a/rules/office365/mail_forwarding_rules.yml +++ b/rules/office365/mail_forwarding_rules.yml @@ -1,33 +1,28 @@ -# Rule version v1.0.0 +# Rule version v1.1.2 dataTypes: - - o365 +- o365 name: Suspicious Mail Forwarding Rule Creation -impact: - confidentiality: 3 - integrity: 2 - availability: 1 -category: Data Exfiltration -technique: "T1114.001 - Email Collection: Local Email Collection" -adversary: origin -references: - - https://docs.microsoft.com/en-us/microsoft-365/compliance/auditing-troubleshooting-scenarios - - https://attack.mitre.org/techniques/T1114/001/ description: | - Detects creation or modification of inbox rules that forward emails to external recipients, which could indicate data exfiltration attempts. This rule monitors for the creation of new inbox rules or modifications to existing rules that contain forwarding parameters. + An inbox rule was created or changed with a ForwardTo, ForwardAsAttachmentTo or RedirectTo setting. Rules that send a mailbox's mail to an outside address are a common sign that the mailbox has been taken over. - Next Steps: - 1. Review the specific forwarding parameters in the log.Parameters field to identify the destination email address - 2. Verify if the forwarding destination is a legitimate business email or an external/suspicious address - 3. Check if the user who created the rule has legitimate business justification for email forwarding - 4. Review recent authentication logs for the affected user account for signs of compromise - 5. Examine the timing of the rule creation - if created outside business hours or immediately after login, investigate further - 6. Check for other suspicious activities by the same user account around the same timeframe - 7. If malicious, disable the forwarding rule and reset user credentials + Check the destination in the rule parameters, who made the change and recent sign-ins for the mailbox. Clearing a forwarding setting in an existing rule also raises this alert. The alert does not by itself establish compromise or an external recipient. +category: Collection +technique: 'T1114.003 - Email Collection: Email Forwarding Rule' +adversary: origin +impact: + confidentiality: 2 + integrity: 1 + availability: 0 +references: +- https://learn.microsoft.com/en-us/purview/audit-log-activities +- https://learn.microsoft.com/en-us/office/office-365-management-api/office-365-management-activity-api-schema +- https://learn.microsoft.com/en-us/powershell/module/exchangepowershell/set-inboxrule?view=exchange-ps where: | - oneOf("action", ["New-InboxRule", "Set-InboxRule", "UpdateInboxRules"]) && - equals("actionResult", "success") && - (contains("log.Parameters", "ForwardTo") || contains("log.Parameters", "ForwardAsAttachmentTo") || contains("log.Parameters", "RedirectTo")) + equals("log.Workload", "Exchange") && equals("actionResult", "success") && oneOf("action", ["New-InboxRule", "Set-InboxRule"]) && (equals("log.o365InboxForwardingChange", "true") || exists("log.Parameters.#(Name==ForwardTo).Name") || exists("log.Parameters.#(Name==ForwardAsAttachmentTo).Name") || exists("log.Parameters.#(Name==RedirectTo).Name")) groupBy: - - adversary.ip - - adversary.user +- lastEvent.tenantId +- lastEvent.log.OrganizationId +- dataSource +- adversary.user +- lastEvent.action diff --git a/rules/office365/mailbox_auto_forwarding_set_mailbox.yml b/rules/office365/mailbox_auto_forwarding_set_mailbox.yml index 0509cf95c..977d91e97 100644 --- a/rules/office365/mailbox_auto_forwarding_set_mailbox.yml +++ b/rules/office365/mailbox_auto_forwarding_set_mailbox.yml @@ -1,21 +1,28 @@ -# Rule version v1.0.0 +# Rule version v1.1.2 dataTypes: - - "o365" -name: "O365 Mailbox Auto-Forwarding (Set-Mailbox)" -impact: - confidentiality: 3 - integrity: 2 - availability: 1 -category: "Data Exfiltration" -technique: "T1114.003 - Email Collection: Email Forwarding Rule" +- o365 +name: O365 Mailbox Auto-Forwarding (Set-Mailbox) +description: | + Set-Mailbox set a forwarding address on a mailbox (ForwardingSmtpAddress or ForwardingAddress). Mail delivered to the mailbox is then forwarded to that address without any inbox rule, a common step after a mailbox is taken over. + + Check whether the address is outside the organization, who made the change and recent sign-ins for that account. Clearing forwarding, or changing only DeliverToMailboxAndForward, does not raise this alert. The alert does not by itself establish compromise or an external recipient. +category: Collection +technique: 'T1114.003 - Email Collection: Email Forwarding Rule' adversary: origin -description: "Detects when a mailbox is configured to automatically forward mail to another address via Set-Mailbox (the OWA \"Forwarding\" setting). The forwarded address appears in the ForwardingSmtpAddress parameter. Attackers set this to exfiltrate all of a mailbox's mail to an off-tenant or external address without creating an inbox rule, so legacy New-InboxRule / Set-InboxRule detections miss it. Note: this rule matches the indexed string element of the Parameters array (ForwardingSmtpAddress, value of the form smtp:
). Investigate whether the forwarding address is authorized and whether it is external (off-tenant)." +impact: + confidentiality: 2 + integrity: 1 + availability: 0 references: - - "https://learn.microsoft.com/en-us/purview/audit-log-activities" - - "https://learn.microsoft.com/en-us/purview/audit-mailbox-settings" - - "https://attack.mitre.org/techniques/T1114/003/" +- https://learn.microsoft.com/en-us/purview/audit-log-activities +- https://learn.microsoft.com/en-us/office/office-365-management-api/office-365-management-activity-api-schema +- https://learn.microsoft.com/en-us/powershell/module/exchangepowershell/set-mailbox?view=exchange-ps where: | - equals("log.Workload", "Exchange") && equals("action", "Set-Mailbox") && contains("log.Parameters", "smtp:") && equals("actionResult", "success") + equals("log.Workload", "Exchange") && equals("actionResult", "success") && equals("action", "Set-Mailbox") && (equals("log.o365MailboxForwardingSet", "true") || regexMatch("log.Parameters.#(Name==ForwardingAddress).Value", "(?s)^.+$") || regexMatch("log.Parameters.#(Name==ForwardingSmtpAddress).Value", "(?s)^.+$")) groupBy: - - adversary.user +- lastEvent.tenantId +- lastEvent.log.OrganizationId +- dataSource +- adversary.user +- lastEvent.action diff --git a/rules/office365/mailbox_delegation_abuse.yml b/rules/office365/mailbox_delegation_abuse.yml index 982191273..bcbda9c37 100644 --- a/rules/office365/mailbox_delegation_abuse.yml +++ b/rules/office365/mailbox_delegation_abuse.yml @@ -1,36 +1,28 @@ -# Rule version v1.0.0 +# Rule version v1.1.2 dataTypes: - - o365 -name: Office 365 Mailbox Delegation Abuse -impact: - confidentiality: 3 - integrity: 2 - availability: 1 -category: Persistence -technique: "T1098.002 - Account Manipulation: Additional Email Delegate Permissions" -adversary: origin -references: - - https://learn.microsoft.com/en-us/exchange/recipients-in-exchange-online/manage-permissions-for-recipients - - https://attack.mitre.org/techniques/T1098/002/ +- o365 +name: Office 365 Mailbox Delegate Permission Changed description: | - Detects addition of mailbox delegation permissions including FullAccess, SendAs, and SendOnBehalf. Attackers may add mailbox permissions to access sensitive emails, send phishing messages as the compromised user, or maintain persistent access to communications. + An administrator granted a mailbox permission such as FullAccess with Add-MailboxPermission, granted SendAs with Add-RecipientPermission, or supplied GrantSendOnBehalfTo to Set-Mailbox. These permissions let another account read the mailbox or send mail as, or on behalf of, its owner. Removing a permission does not raise this alert. - Next Steps: - 1. Verify the mailbox delegation was authorized by the mailbox owner or administrator - 2. Review the specific permissions granted (FullAccess, SendAs, SendOnBehalf) - 3. Check who the delegate user is and their relationship to the mailbox owner - 4. Review recent authentication activity for both the admin and delegate accounts - 5. Examine the timing of the delegation for suspicious patterns - 6. If unauthorized, remove the delegation permissions immediately - 7. Review the mailbox for signs of unauthorized access or data theft - 8. Enable mailbox audit logging if not already enabled + Some changes are recorded under an Exchange service account instead of the administrator who made them. Review the actor, affected object, change request and authorized owner. This alert reports an audited configuration change; it does not by itself establish compromise, an external recipient, or a currently enabled setting. +category: Administrative Awareness +technique: 'T1098.002 - Account Manipulation: Additional Email Delegate Permissions' +adversary: origin +impact: + confidentiality: 1 + integrity: 1 + availability: 0 +references: +- https://learn.microsoft.com/en-us/purview/audit-log-activities +- https://learn.microsoft.com/en-us/office/office-365-management-api/office-365-management-activity-api-schema +- https://learn.microsoft.com/en-us/powershell/module/exchangepowershell/add-mailboxpermission?view=exchange-ps where: | - oneOf("action", ["Add-MailboxPermission", "Add-RecipientPermission", "Set-Mailbox"]) && - equals("actionResult", "success") && - (contains("log.Parameters", "FullAccess") || - contains("log.Parameters", "SendAs") || - contains("log.Parameters", "SendOnBehalf")) + equals("log.Workload", "Exchange") && equals("actionResult", "success") && (oneOf("action", ["Add-MailboxPermission", "Add-RecipientPermission"]) || (equals("action", "Set-Mailbox") && (equals("log.o365SendOnBehalfChange", "true") || exists("log.Parameters.#(Name==GrantSendOnBehalfTo).Name")))) groupBy: - - adversary.user - - target.user +- lastEvent.tenantId +- lastEvent.log.OrganizationId +- dataSource +- adversary.user +- lastEvent.action diff --git a/rules/office365/possible_succesfull_password_guessing_o365.yml b/rules/office365/possible_succesfull_password_guessing_o365.yml index 1c17e8b10..d8f95b26a 100644 --- a/rules/office365/possible_succesfull_password_guessing_o365.yml +++ b/rules/office365/possible_succesfull_password_guessing_o365.yml @@ -1,4 +1,4 @@ -# Rule version v1.0.0 +# Rule version v1.0.1 dataTypes: - o365 @@ -21,7 +21,7 @@ references: - "https://attack.mitre.org/tactics/TA0006" - "https://attack.mitre.org/techniques/T1110/001/" where: | - oneOf("log.Workload", ["Exchange","AzureActiveDirectory"]) && equals("action", "UserLoginFailed") && oneOf("actionResult", ["failed"]) && exists("origin.user") && exists("origin.ip") + oneOf("log.Workload", ["Exchange","AzureActiveDirectory"]) && equals("action", "UserLoginFailed") && oneOf("actionResult", ["failure", "failed"]) && exists("origin.user") && exists("origin.ip") afterEvents: - indexPattern: v11-log-o365-* with: @@ -33,7 +33,7 @@ afterEvents: value: "{{.origin.user}}" - field: origin.ip operator: filter_term - value: "{{.log.clientIP}}" + value: "{{.origin.ip}}" within: 1m count: 10 groupBy: diff --git a/rules/office365/safe_links_click_patterns.yml b/rules/office365/safe_links_click_patterns.yml index 5ee89a314..6421ff26e 100644 --- a/rules/office365/safe_links_click_patterns.yml +++ b/rules/office365/safe_links_click_patterns.yml @@ -1,4 +1,4 @@ -# Rule version v1.0.0 +# Rule version v1.0.1 dataTypes: - o365 @@ -24,7 +24,7 @@ description: | 5. Implement additional security awareness training for the affected user 6. Consider blocking the malicious domains at the network level where: | - equals("action", "ClickedSafeLink") && equals("actionResult", "blocked") && exists("origin.user") + equals("action", "ClickedSafeLink") && oneOf("actionResult", ["denied", "blocked"]) && exists("origin.user") afterEvents: - indexPattern: v11-log-o365-* with: diff --git a/rules/office365/suspicious_inbox_rules.yml b/rules/office365/suspicious_inbox_rules.yml deleted file mode 100644 index 8a8c27a3f..000000000 --- a/rules/office365/suspicious_inbox_rules.yml +++ /dev/null @@ -1,31 +0,0 @@ -# Rule version v1.0.0 - -dataTypes: - - o365 -name: Suspicious Email Forwarding Rule Created -impact: - confidentiality: 3 - integrity: 2 - availability: 1 -category: Persistence -technique: "T1114.003 - Email Collection: Email Forwarding Rule" -adversary: origin -references: - - https://redcanary.com/blog/threat-detection/email-forwarding-rules/ - - https://attack.mitre.org/techniques/T1114/003/ -description: | - Detects creation or modification of inbox rules that forward emails to external domains, which is a common technique used by attackers to exfiltrate emails and maintain persistence after compromising an account. Attackers often create these rules to automatically forward sensitive emails to external addresses under their control. - - Next Steps: - 1. Verify if the user creating the rule is legitimate and authorized - 2. Check the destination email address in the forwarding rule for external domains - 3. Review recent authentication logs for the affected user account - 4. Examine other administrative actions performed by this user recently - 5. Check for any other suspicious inbox rules created by the same user - 6. Validate if the forwarding address belongs to a legitimate business contact - 7. Consider temporarily disabling the forwarding rule pending investigation - 8. Review email logs to see what emails may have already been forwarded -where: | - oneOf("action", ["New-InboxRule", "Set-InboxRule"]) && exists("origin.user") && (contains("log.Parameters", "ForwardTo") || contains("log.Parameters", "RedirectTo") || contains("log.Parameters", "ForwardAsAttachmentTo")) -groupBy: - - adversary.user