{
  "version": "Notebook/1.0",
  "items": [
    {
      "type": 1,
      "content": {
        "json": "# Microsoft Exchange Security Review Online"
      },
      "name": "text - 2"
    },
    {
      "type": 9,
      "content": {
        "version": "KqlParameterItem/1.0",
        "parameters": [
          {
            "id": "9ae328d6-99c8-4c44-8d59-42ca4d999098",
            "version": "KqlParameterItem/1.0",
            "name": "EnvironmentList",
            "label": "Environment",
            "type": 2,
            "isRequired": true,
            "multiSelect": true,
            "quote": "'",
            "delimiter": ",",
            "query": "ExchangeEnvironmentList(Target=\"Online\") | where ESIEnvironment != \"\"",
            "typeSettings": {
              "limitSelectTo": 1,
              "showDefault": false
            },
            "queryType": 0,
            "resourceType": "microsoft.operationalinsights/workspaces",
            "value": []
          },
          {
            "id": "a88b4e41-eb2f-41bf-92d8-27c83650a4b8",
            "version": "KqlParameterItem/1.0",
            "name": "DateOfConfiguration",
            "label": "Collection time",
            "type": 2,
            "isRequired": true,
            "query": "let _configurationEnv = split(iff(isnull({EnvironmentList}) or isempty({EnvironmentList}) or tolower({EnvironmentList}) == \"all\",\"All\",tostring({EnvironmentList})),',');\r\nESIExchangeOnlineConfig_CL\r\n| extend ScopedEnvironment = iff(_configurationEnv contains \"All\", \"All\",ESIEnvironment_s) \r\n| where ScopedEnvironment in (_configurationEnv)\r\n| extend Collection = format_datetime(todatetime(EntryDate_s), 'yyyy-MM-dd')\r\n| summarize Collection = max(Collection)\r\n| project Collection = \"lastdate\", Selected = true\r\n| join kind= fullouter  ( ESIExchangeOnlineConfig_CL | extend ScopedEnvironment = iff(_configurationEnv contains \"All\", \"All\",ESIEnvironment_s) \r\n    | where ScopedEnvironment in (_configurationEnv)\r\n    | where TimeGenerated > ago(90d)\r\n    | extend Collection = format_datetime(todatetime(EntryDate_s), 'yyyy-MM-dd')\r\n    | summarize by Collection \r\n    | join kind= fullouter ( ESIExchangeOnlineConfig_CL | extend ScopedEnvironment = iff(_configurationEnv contains \"All\", \"All\",ESIEnvironment_s) \r\n        | where ScopedEnvironment in (_configurationEnv)\r\n        | where TimeGenerated > ago(90d)\r\n        | extend Collection = format_datetime(todatetime(EntryDate_s), 'yyyy-MM-dd')\r\n        | extend PreciseCollection = format_datetime(todatetime(EntryDate_s), 'yyyy-MM-dd HH:mm ')\r\n        | summarize by PreciseCollection, Collection \r\n        | join kind=leftouter (\r\n            ESIExchangeOnlineConfig_CL | extend ScopedEnvironment = iff(_configurationEnv contains \"All\", \"All\",ESIEnvironment_s) \r\n            | where ScopedEnvironment in (_configurationEnv)\r\n            | where TimeGenerated > ago(90d)\r\n            | extend Collection = format_datetime(todatetime(EntryDate_s), 'yyyy-MM-dd')\r\n            | extend PreciseCollection = format_datetime(todatetime(EntryDate_s), 'yyyy-MM-dd HH:mm')\r\n            | summarize by PreciseCollection, Collection \r\n            | summarize count() by Collection\r\n        ) on Collection\r\n    ) on Collection\r\n) on Collection\r\n| project Value = iif(Selected,Collection,iif(count_ > 1,PreciseCollection,Collection1)), Label = iif(Selected,\"Last Known date\",iif(count_ > 1,PreciseCollection,Collection1)), Selected\r\n| sort by Selected, Value desc",
            "typeSettings": {
              "additionalResourceOptions": [],
              "showDefault": false
            },
            "queryType": 0,
            "resourceType": "microsoft.operationalinsights/workspaces"
          },
          {
            "id": "181fa282-a002-42f1-ad57-dfb86df3194e",
            "version": "KqlParameterItem/1.0",
            "name": "Compare_Collect",
            "type": 10,
            "description": "If this button is checked, two collections will be compared",
            "isRequired": true,
            "typeSettings": {
              "additionalResourceOptions": []
            },
            "jsonData": "[\r\n { \"value\": \"True\", \"label\": \"Yes\" },\r\n { \"value\": \"True,False\", \"label\": \"No\", \"selected\":true }\r\n]"
          },
          {
            "id": "8ac96eb3-918b-4a36-bcc4-df50d8f46175",
            "version": "KqlParameterItem/1.0",
            "name": "Help",
            "label": "Show Help",
            "type": 10,
            "isRequired": true,
            "query": "{\"version\":\"1.0.0\",\"content\":\"[\\r\\n { \\\"value\\\": \\\"Yes\\\", \\\"label\\\": \\\"Yes\\\"},\\r\\n {\\\"value\\\": \\\"No\\\", \\\"label\\\": \\\"No\\\", \\\"selected\\\":true }\\r\\n]\\r\\n\"}\r\n",
            "timeContext": {
              "durationMs": 2592000000
            },
            "queryType": 8
          }
        ],
        "style": "above",
        "queryType": 0,
        "resourceType": "microsoft.operationalinsights/workspaces"
      },
      "name": "TimeRange"
    },
    {
      "type": 9,
      "content": {
        "version": "KqlParameterItem/1.0",
        "parameters": [
          {
            "id": "a9e0099e-5eb1-43b8-915c-587aa05bccf0",
            "version": "KqlParameterItem/1.0",
            "name": "DateCompare",
            "type": 2,
            "description": "Date to Comapre",
            "isRequired": true,
            "query": "let _configurationEnv = split(iff(isnull({EnvironmentList}) or isempty({EnvironmentList}) or tolower({EnvironmentList}) == \"all\",\"All\",tostring({EnvironmentList})),',');\r\nESIExchangeOnlineConfig_CL\r\n| extend ScopedEnvironment = iff(_configurationEnv contains \"All\", \"All\",ESIEnvironment_s) \r\n| where ScopedEnvironment in (_configurationEnv)\r\n| extend Collection = format_datetime(todatetime(EntryDate_s), 'yyyy-MM-dd')\r\n| summarize Collection = max(Collection)\r\n| project Collection = \"lastdate\", Selected = true\r\n| join kind= fullouter  ( ESIExchangeOnlineConfig_CL | extend ScopedEnvironment = iff(_configurationEnv contains \"All\", \"All\",ESIEnvironment_s) \r\n    | where ScopedEnvironment in (_configurationEnv)\r\n    | where TimeGenerated > ago(90d)\r\n    | extend Collection = format_datetime(todatetime(EntryDate_s), 'yyyy-MM-dd')\r\n    | summarize by Collection \r\n    | join kind= fullouter ( ESIExchangeOnlineConfig_CL | extend ScopedEnvironment = iff(_configurationEnv contains \"All\", \"All\",ESIEnvironment_s) \r\n        | where ScopedEnvironment in (_configurationEnv)\r\n        | where TimeGenerated > ago(90d)\r\n        | extend Collection = format_datetime(todatetime(EntryDate_s), 'yyyy-MM-dd')\r\n        | extend PreciseCollection = format_datetime(todatetime(EntryDate_s), 'yyyy-MM-dd HH:mm ')\r\n        | summarize by PreciseCollection, Collection \r\n        | join kind=leftouter (\r\n            ESIExchangeOnlineConfig_CL | extend ScopedEnvironment = iff(_configurationEnv contains \"All\", \"All\",ESIEnvironment_s) \r\n            | where ScopedEnvironment in (_configurationEnv)\r\n            | where TimeGenerated > ago(90d)\r\n            | extend Collection = format_datetime(todatetime(EntryDate_s), 'yyyy-MM-dd')\r\n            | extend PreciseCollection = format_datetime(todatetime(EntryDate_s), 'yyyy-MM-dd HH:mm')\r\n            | summarize by PreciseCollection, Collection \r\n            | summarize count() by Collection\r\n        ) on Collection\r\n    ) on Collection\r\n) on Collection\r\n| project Value = iif(Selected,Collection,iif(count_ > 1,PreciseCollection,Collection1)), Label = iif(Selected,\"Last Known date\",iif(count_ > 1,PreciseCollection,Collection1)), Selected\r\n| sort by Selected, Value desc",
            "typeSettings": {
              "additionalResourceOptions": [],
              "showDefault": false
            },
            "queryType": 0,
            "resourceType": "microsoft.operationalinsights/workspaces"
          }
        ],
        "style": "above",
        "queryType": 0,
        "resourceType": "microsoft.operationalinsights/workspaces"
      },
      "conditionalVisibility": {
        "parameterName": "Compare_Collect",
        "comparison": "isEqualTo",
        "value": "True"
      },
      "name": "parameters - 0"
    },
    {
      "type": 1,
      "content": {
        "json": "This workbook helps review your Exchange Security configuration.\r\nAdjust the time range, and when needed select an item in the dropdownlist",
        "style": "info"
      },
      "name": "text - 9"
    },
    {
      "type": 11,
      "content": {
        "version": "LinkItem/1.0",
        "style": "tabs",
        "links": [
          {
            "id": "34188faf-7a02-4697-9b36-2afa986afc0f",
            "cellValue": "selected",
            "linkTarget": "parameter",
            "linkLabel": "Mailbox Access",
            "subTarget": "Delegation",
            "postText": "t",
            "style": "link",
            "icon": "3",
            "linkIsContextBlade": true
          },
          {
            "id": "be02c735-6150-4b6e-a386-b2b023e754e5",
            "cellValue": "selected",
            "linkTarget": "parameter",
            "linkLabel": "EXO & Azure AD Groups",
            "subTarget": "ExchAD",
            "style": "link"
          },
          {
            "id": "26c68d90-925b-4c3c-a837-e3cecd489b2d",
            "cellValue": "selected",
            "linkTarget": "parameter",
            "linkLabel": "Transport Configuration",
            "subTarget": "Transport",
            "style": "link"
          },
          {
            "id": "eb2888ca-7fa6-4e82-88db-1bb3663a801e",
            "cellValue": "selected",
            "linkTarget": "parameter",
            "linkLabel": "Workbook Help",
            "subTarget": "Start",
            "style": "link"
          }
        ]
      },
      "name": "TopMenuTabs"
    },
    {
      "type": 1,
      "content": {
        "json": "To compare collects, select **Yes** and choose the initial date.\r\nFor each role, a new table will be displayed with **all** the modifications (Add, Remove, Modifications) beetween the two dates.\r\n\r\n**Important notes** : Some information are limited are may be not 100% accurate :\r\n  - Date\r\n  - GUID of user instead of the name\r\n  - Fusion of modifications when a role assisgnment is changed within the same collect \r\n  - ... \r\n\r\nThis is due to some restrictions in the collect. For more details information, please check the workbook **\"Microsoft Exchange Search AdminAuditLog - Online\"**\r\n.\r\n\r\nThe compare functionnality is not available for all sections in this workbook.\r\n"
      },
      "name": "text - 9"
    },
    {
      "type": 12,
      "content": {
        "version": "NotebookGroup/1.0",
        "groupType": "editable",
        "items": [
          {
            "type": 1,
            "content": {
              "json": "# Workbook goals\r\n\r\nThe goal of this workbook is to outline key security configurations of your Exchange on-premises environment.\r\n\r\nMost of Exchange organizations have were installed years ago (sometimes more than 10 years). Many configurations have been done and might not have been documented. For most environments, the core commitment was maintaining a high availability of the users’ mailboxes putting aside other consideration (even security considerations). Recommended security practices have also evolved since the first released and a regular review is necessary.\r\n\r\nThis workbook is designed to show your Exchange organization is configured with a security point of view. Indeed, some configurations easy to display as there are no UI available.\r\n\r\nFor each configuration, you will find explanations and recommendations when applicable.\r\n\r\n- This workbook does not pretend to show you every weak Security configurations, but the most common issues and known to be used by attackers. \r\n- It will not show you if you have been comprised, but will help you identify unexpected configuration.\r\n\r\n----\r\n\r\n## Quick reminder of how Exchange works\r\n\r\nDuring Exchange installation two very important groups are created :\r\n- Exchange Trusted Subsystem : Contain all the computer accounts for Exchange Server\r\n- Exchange Windows Permissions : Contain the group Exchange trusted Subsystem\r\n\r\nThese groups have :\r\n- Very high privileges in ALL AD domains including the root domain\r\n- Right on any Exchange including mailboxes\r\n\r\nAs each Exchange server computer account is member of Exchange Trusted Subsystem, it means by taking control of the computer account or being System on an Exchange server you will gain access to all the permissions granted to Exchange Trusted Subsystem and Exchange Windows Permissions.\r\n\r\nTo protect AD and Exchange, it is very important to ensure the following:\r\n- There is a very limited number of persons that are local Administrator on Exchange server\r\n- To protect user right like : Act part of the operating System, Debug\r\n\r\nEvery service account or application that have high privileges on Exchange need to be considered as sensitive\r\n\r\n** 💡 Exchange servers need to be considered as very sensitive servers**\r\n\r\n-----\r\n\r\n\r\n## Tabs\r\n\r\n### Mailbox Access\r\n\r\nThis tab will show you several top sensitive delegations that allow an account to access, modify, act as another user, search, export the content of a mailbox.\r\n\r\n### Exchange & AD Groups\r\n\r\nThis tab will show you the members of Exchange groups and Sensitive AD groups.\r\n\r\n### Local Administrators\r\n\r\nThis tab will show you the non standard content of the local Administrators group. Remember that a member of the local Administrators group can take control of the computer account of the server and then it will have all the permissions associated with Exchange Trusted Subsytem and Exchange Windows Permissions\r\n\r\nThe information is displayed with different views : \r\n- List of nonstandard users\r\n- Number of servers with a nonstandard a user\r\n- Nonstandard groups content\r\n- For each user important information are displayed like last logon, last password set, enabled\r\n\r\n### Exchange Security configuration\r\n\r\nThis tab will show you some important configuration for your Exchange Organization\r\n- Status of Admin Audit Log configuration\r\n- Status of POP and IMAP configuration : especially, is Plaintext Authentication configured ?\r\n- Nonstandard permissions on the Exchange container in the Configuration Partition\r\n\r\n### Transport Configuration\r\n\r\nThis tab will show you the configuration of the main Transport components\r\n- Receive Connectors configured with Anonymous and/or Open Relay\r\n- Remote Domain Autoforward configuration\r\n- Transport Rules configured with BlindCopyTo, SendTo, RedirectTo\r\n- Journal Rule and Journal Recipient configurations\r\n- Accepted Domains with *\r\n\r\n"
            },
            "name": "WorkbookInfo"
          }
        ]
      },
      "conditionalVisibility": {
        "parameterName": "selected",
        "comparison": "isEqualTo",
        "value": "Start"
      },
      "name": "InformationTab"
    },
    {
      "type": 12,
      "content": {
        "version": "NotebookGroup/1.0",
        "groupType": "editable",
        "title": "Display important security configurations that allow to access mailboxes' content. Direct delegations on mailboxes are not listed (Full Access permission mailboxes or direct delegations on mailboxes  folders)",
        "items": [
          {
            "type": 3,
            "content": {
              "version": "KqlItem/1.0",
              "query": "ExchangeConfiguration(SpecificSectionList=\"MRA\",SpecificConfigurationDate=\"{DateOfConfiguration:value}\",SpecificConfigurationEnv={EnvironmentList},Target = \"Online\")\r\n| where CmdletResultValue.Name !contains \"Deleg\" and CmdletResultValue.RoleAssigneeName != \"Hygiene Management\" and  CmdletResultValue.RoleAssigneeName != \"Exchange Online-ApplicationAccount\" and CmdletResultValue.RoleAssigneeName != \"Discovery Management\" and CmdletResultValue.RoleAssigneeName !contains \"RIM-MailboxAdmins\"\r\n| where CmdletResultValue.Role contains \"Export\" or CmdletResultValue.Role contains \"Impersonation\" or CmdletResultValue.Role contains \"Search\"\r\n| summarize dcount(tostring(CmdletResultValue.RoleAssigneeName)) by role=tostring(CmdletResultValue.Role)",
              "size": 3,
              "title": "Number of accounts with sensitive RBAC roles",
              "queryType": 0,
              "resourceType": "microsoft.operationalinsights/workspaces",
              "visualization": "tiles",
              "tileSettings": {
                "titleContent": {
                  "columnMatch": "role",
                  "formatter": 1
                },
                "leftContent": {
                  "columnMatch": "dcount_CmdletResultValue_RoleAssigneeName",
                  "formatter": 12,
                  "formatOptions": {
                    "palette": "auto"
                  },
                  "numberFormat": {
                    "unit": 17,
                    "options": {
                      "style": "decimal",
                      "maximumFractionDigits": 2,
                      "maximumSignificantDigits": 3
                    }
                  }
                },
                "showBorder": true,
                "sortCriteriaField": "role",
                "sortOrderField": 1
              }
            },
            "name": "MRAQuery"
          },
          {
            "type": 1,
            "content": {
              "json": "**ApplicationImpersonation** is a RBAC role that allows access (read and modify) to the content of all mailboxes. This role is very powerfull and should be carefully delegated. When a delegation is necessary, RBAC scopes should be configured to limit the list of impacted mailboxes.\r\n\r\nIt is common to see service accounts for backup solution, antivirus software, MDM...",
              "style": "info"
            },
            "conditionalVisibility": {
              "parameterName": "Help",
              "comparison": "isEqualTo",
              "value": "Yes"
            },
            "name": "SensitiveRBACHelp"
          },
          {
            "type": 12,
            "content": {
              "version": "NotebookGroup/1.0",
              "groupType": "editable",
              "title": "Application Impersonation Role",
              "items": [
                {
                  "type": 1,
                  "content": {
                    "json": "This delegation allows the delegated account to access and modify the content of every mailboxes using EWS.\r\nExcluded from the result as it is a default configuration :\r\nDelegating delegation to Organization Management"
                  },
                  "name": "text - 0"
                },
                {
                  "type": 3,
                  "content": {
                    "version": "KqlItem/1.0",
                    "query": "ExchangeConfiguration(SpecificSectionList=\"MRA\",SpecificConfigurationDate=\"{DateOfConfiguration:value}\",SpecificConfigurationEnv={EnvironmentList},Target = \"Online\")\r\n| where CmdletResultValue.Role contains \"Impersonation\" and CmdletResultValue.RoleAssigneeName != \"Hygiene Management\" and CmdletResultValue.RoleAssigneeName !contains \"RIM-MailboxAdmins\" and CmdletResultValue.Name !contains \"Deleg\"\r\n| extend RoleAssigneeName = tostring(CmdletResultValue.RoleAssigneeName)\r\n| extend RoleAssigneeType = iff(CmdletResultValue.RoleAssigneeType== \"User\" , \"User\", \"RoleGroup\")\r\n| extend CustomRecipientWriteScope = tostring(CmdletResultValue.CustomRecipientWriteScope)\r\n| extend CustomConfigWriteScope = tostring(CmdletResultValue.CustomConfigWriteScope)\r\n| extend CustomResourceScope = tostring(CmdletResultValue.CustomResourceScope)\r\n| extend RecipientWriteScope = CmdletResultValue.RecipientWriteScope\r\n| extend ConfigWriteScope = CmdletResultValue.ConfigWriteScope\r\n| extend ManagementRoleAssignement = tostring(CmdletResultValue.Name)\r\n| extend Status= tostring(CmdletResultValue.Enabled)\r\n| extend RoleAssigneeName = iff( RoleAssigneeType == \"User\", strcat(\"🧑‍🦰 \",RoleAssigneeName), strcat(\"👪 \", RoleAssigneeName) )\r\n| project RoleAssigneeName, RoleAssigneeType, Status,CustomRecipientWriteScope,CustomConfigWriteScope,CustomResourceScope,RecipientWriteScope,ConfigWriteScope,ManagementRoleAssignement,WhenChanged,WhenCreated",
                    "size": 3,
                    "showAnalytics": true,
                    "showExportToExcel": true,
                    "queryType": 0,
                    "resourceType": "microsoft.operationalinsights/workspaces",
                    "gridSettings": {
                      "rowLimit": 10000,
                      "filter": true
                    }
                  },
                  "name": "query - 1",
                  "styleSettings": {
                    "showBorder": true
                  }
                },
                {
                  "type": 3,
                  "content": {
                    "version": "KqlItem/1.0",
                    "query": "let ExclusionsAcctValue = dynamic([\"Hygiene Management\", \"RIM-MailboxAdmins\"]);\r\nMESCompareDataMRA(SectionCompare=\"MRA\",DateCompare=\"{DateCompare:value}\",CurrentDate = \"{DateOfConfiguration:value}\",EnvList ={EnvironmentList},TypeEnv = \"Online\",ExclusionsAcct = ExclusionsAcctValue ,CurrentRole=\"Impersonation\")",
                    "size": 3,
                    "title": "Display changes ( Add, Remove, modifications of parameters )",
                    "queryType": 0,
                    "resourceType": "microsoft.operationalinsights/workspaces",
                    "gridSettings": {
                      "hierarchySettings": {
                        "treeType": 1,
                        "groupBy": [
                          "ManagementRoleAssignement"
                        ],
                        "expandTopLevel": true
                      }
                    }
                  },
                  "conditionalVisibility": {
                    "parameterName": "Compare_Collect",
                    "comparison": "isEqualTo",
                    "value": "True"
                  },
                  "name": "query - 2"
                }
              ]
            },
            "name": "Application Impersonation Role"
          },
          {
            "type": 12,
            "content": {
              "version": "NotebookGroup/1.0",
              "groupType": "editable",
              "title": "Mailbox Import Export Role",
              "items": [
                {
                  "type": 1,
                  "content": {
                    "json": "This delegation allows to import contents in all  mailboxes.\r\nExcluded from the result as it is a default configuration :\r\nDelegating delegation to Organization Management\r\n"
                  },
                  "name": "text - 0"
                },
                {
                  "type": 1,
                  "content": {
                    "json": "**Mailbox Import Export**  is an RBAC role that allows an account to import (export is not available online) contant in a user mailbox. It also allows searches in all mailboxes.\r\n\r\n⚡ This role is very powerfull.\r\n\r\nBy default, this role is not delegated to any user or group. The members of the group Organization Management by default do not have this role but are able to delegate it.\r\n\r\nℹ️ Recommendations\r\n\r\nIf you temporarily need this delegation, consider the following:\r\n- create an empty group with this delegation\r\n- monitor the group content and  alert when the group modified\r\n- add administrators in this group only for a short period of time",
                    "style": "info"
                  },
                  "conditionalVisibility": {
                    "parameterName": "Help",
                    "comparison": "isEqualTo",
                    "value": "Yes"
                  },
                  "name": "SearchRBACHelp"
                },
                {
                  "type": 3,
                  "content": {
                    "version": "KqlItem/1.0",
                    "query": "ExchangeConfiguration(SpecificSectionList=\"MRA\",SpecificConfigurationDate=\"{DateOfConfiguration:value}\",SpecificConfigurationEnv={EnvironmentList},Target = \"Online\")\r\n| where CmdletResultValue.Role contains \"export\" and CmdletResultValue.Name !contains \"Deleg\"\r\n| extend RoleAssigneeName = tostring(CmdletResultValue.RoleAssigneeName)\r\n| extend RoleAssigneeType = iff(CmdletResultValue.RoleAssigneeType== \"User\" , \"User\", \"RoleGroup\")\r\n| extend CustomRecipientWriteScope = tostring(CmdletResultValue.CustomRecipientWriteScope)\r\n| extend CustomConfigWriteScope = tostring(CmdletResultValue.CustomConfigWriteScope)\r\n| extend CustomResourceScope = tostring(CmdletResultValue.CustomResourceScope)\r\n| extend RecipientWriteScope = CmdletResultValue.RecipientWriteScope\r\n| extend ConfigWriteScope = CmdletResultValue.ConfigWriteScope\r\n| extend ManagementRoleAssignement = tostring(CmdletResultValue.Name)\r\n| extend Status= tostring(CmdletResultValue.Enabled)\r\n| extend RoleAssigneeName = iff( RoleAssigneeType == \"User\", strcat(\"🧑‍🦰 \",RoleAssigneeName), strcat(\"👪 \", RoleAssigneeName) )\r\n| project RoleAssigneeName, RoleAssigneeType, Status,CustomRecipientWriteScope,CustomConfigWriteScope,CustomResourceScope,RecipientWriteScope,ConfigWriteScope,ManagementRoleAssignement,WhenChanged,WhenCreated",
                    "size": 3,
                    "showAnalytics": true,
                    "showExportToExcel": true,
                    "queryType": 0,
                    "resourceType": "microsoft.operationalinsights/workspaces",
                    "gridSettings": {
                      "rowLimit": 10000,
                      "filter": true,
                      "sortBy": [
                        {
                          "itemKey": "ConfigWriteScope",
                          "sortOrder": 1
                        }
                      ]
                    },
                    "sortBy": [
                      {
                        "itemKey": "ConfigWriteScope",
                        "sortOrder": 1
                      }
                    ]
                  },
                  "name": "query - 1",
                  "styleSettings": {
                    "showBorder": true
                  }
                },
                {
                  "type": 3,
                  "content": {
                    "version": "KqlItem/1.0",
                    "query": "MESCompareDataMRA(SectionCompare=\"MRA\",DateCompare=\"{DateCompare:value}\",CurrentDate = \"{DateOfConfiguration:value}\",EnvList ={EnvironmentList},TypeEnv = \"Online\",ExclusionsAcct = \"N/A\",CurrentRole=\"export\")",
                    "size": 3,
                    "showAnalytics": true,
                    "title": "Display changes ( Add, Remove, modifications of parameters )",
                    "showExportToExcel": true,
                    "queryType": 0,
                    "resourceType": "microsoft.operationalinsights/workspaces",
                    "gridSettings": {
                      "rowLimit": 10000,
                      "filter": true,
                      "hierarchySettings": {
                        "treeType": 1,
                        "groupBy": [
                          "ManagementRoleAssignement"
                        ],
                        "expandTopLevel": true
                      },
                      "sortBy": [
                        {
                          "itemKey": "ConfigWriteScope",
                          "sortOrder": 1
                        }
                      ]
                    },
                    "sortBy": [
                      {
                        "itemKey": "ConfigWriteScope",
                        "sortOrder": 1
                      }
                    ]
                  },
                  "conditionalVisibility": {
                    "parameterName": "Compare_Collect",
                    "comparison": "isEqualTo",
                    "value": "True"
                  },
                  "name": "query - 1 - Copy",
                  "styleSettings": {
                    "showBorder": true
                  }
                }
              ]
            },
            "name": "Mailbox Import Export Role"
          },
          {
            "type": 12,
            "content": {
              "version": "NotebookGroup/1.0",
              "groupType": "editable",
              "title": "Mailbox Search Role",
              "items": [
                {
                  "type": 1,
                  "content": {
                    "json": "This delegation allows to search inside all or in a scope of mailboxes.\r\nExcluded from the result as it is a default configuration :\r\nDelegating delegation to Organization Management\r\nDiscovery Management has been excluded\r\n"
                  },
                  "name": "text - 0"
                },
                {
                  "type": 1,
                  "content": {
                    "json": "**Mailbox Search** is an RBAC role that allows an account to search in any mailbox.\r\n\r\n⚡ This role is very powerfull.\r\n\r\nBy default, this role is only delegated to the group Discovery Management. The members of the group Organization Management do not have this role but are able to delegate it.\r\n\r\nℹ️ Recommendations\r\n\r\nIf you temporarily need this delegation, consider the following:\r\n\r\n- add the administrators in the Discovery Management group\r\n- monitor the group content and alert when the group modified\r\n- add administrators in this group only for a short period of time",
                    "style": "info"
                  },
                  "conditionalVisibility": {
                    "parameterName": "Help",
                    "comparison": "isEqualTo",
                    "value": "Yes"
                  },
                  "name": "SearchRBACHelp"
                },
                {
                  "type": 3,
                  "content": {
                    "version": "KqlItem/1.0",
                    "query": "ExchangeConfiguration(SpecificSectionList=\"MRA\",SpecificConfigurationDate=\"{DateOfConfiguration:value}\",SpecificConfigurationEnv={EnvironmentList},Target = \"Online\")\r\n| where CmdletResultValue.Role contains \"search\" and CmdletResultValue.Name !contains \"Deleg\"\r\n| where CmdletResultValue.RoleAssigneeName != \"Exchange Online-ApplicationAccount\" and CmdletResultValue.RoleAssigneeName != \"Discovery Management\"\r\n| extend RoleAssigneeName = tostring(CmdletResultValue.RoleAssigneeName)\r\n| extend RoleAssigneeType = iff(CmdletResultValue.RoleAssigneeType== \"User\" , \"User\", \"Group\")\r\n| extend CustomRecipientWriteScope = tostring(CmdletResultValue.CustomRecipientWriteScope)\r\n| extend CustomConfigWriteScope = tostring(CmdletResultValue.CustomConfigWriteScope)\r\n| extend CustomResourceScope = tostring(CmdletResultValue.CustomResourceScope)\r\n| extend RecipientWriteScope = CmdletResultValue.RecipientWriteScope\r\n| extend ConfigWriteScope = CmdletResultValue.ConfigWriteScope\r\n| extend ManagementRoleAssignement = tostring(CmdletResultValue.Name)\r\n| extend Status= tostring(CmdletResultValue.Enabled)\r\n| extend RoleAssigneeName = iff( RoleAssigneeType == \"User\", strcat(\"🧑‍🦰 \",RoleAssigneeName), strcat(\"👪 \", RoleAssigneeName) )\r\n| project RoleAssigneeName, RoleAssigneeType, Status,CustomRecipientWriteScope,CustomConfigWriteScope,CustomResourceScope,RecipientWriteScope,ConfigWriteScope,ManagementRoleAssignement,WhenChanged,WhenCreated",
                    "size": 3,
                    "showAnalytics": true,
                    "showExportToExcel": true,
                    "queryType": 0,
                    "resourceType": "microsoft.operationalinsights/workspaces",
                    "gridSettings": {
                      "rowLimit": 10000,
                      "filter": true,
                      "sortBy": [
                        {
                          "itemKey": "ConfigWriteScope",
                          "sortOrder": 1
                        }
                      ]
                    },
                    "sortBy": [
                      {
                        "itemKey": "ConfigWriteScope",
                        "sortOrder": 1
                      }
                    ]
                  },
                  "name": "query - 1",
                  "styleSettings": {
                    "showBorder": true
                  }
                },
                {
                  "type": 3,
                  "content": {
                    "version": "KqlItem/1.0",
                    "query": "MESCompareDataMRA(SectionCompare=\"MRA\",DateCompare=\"{DateCompare:value}\",CurrentDate = \"{DateOfConfiguration:value}\",EnvList ={EnvironmentList},TypeEnv = \"Online\",ExclusionsAcct = \"N/A\",CurrentRole=\"Search\")",
                    "size": 3,
                    "showAnalytics": true,
                    "title": "Display changes ( Add, Remove, modifications of parameters )",
                    "showExportToExcel": true,
                    "queryType": 0,
                    "resourceType": "microsoft.operationalinsights/workspaces",
                    "gridSettings": {
                      "rowLimit": 10000,
                      "filter": true,
                      "hierarchySettings": {
                        "treeType": 1,
                        "groupBy": [
                          "ManagementRoleAssignement"
                        ],
                        "expandTopLevel": true
                      },
                      "sortBy": [
                        {
                          "itemKey": "ConfigWriteScope",
                          "sortOrder": 1
                        }
                      ]
                    },
                    "sortBy": [
                      {
                        "itemKey": "ConfigWriteScope",
                        "sortOrder": 1
                      }
                    ]
                  },
                  "conditionalVisibility": {
                    "parameterName": "Compare_Collect",
                    "comparison": "isEqualTo",
                    "value": "True"
                  },
                  "name": "query - 1 - Copy",
                  "styleSettings": {
                    "showBorder": true
                  }
                }
              ]
            },
            "name": "Mailbox Search Role"
          }
        ]
      },
      "conditionalVisibility": {
        "parameterName": "selected",
        "comparison": "isEqualTo",
        "value": "Delegation"
      },
      "name": "Importantsecurityconfiguration"
    },
    {
      "type": 12,
      "content": {
        "version": "NotebookGroup/1.0",
        "groupType": "editable",
        "title": "Exchange Group",
        "items": [
          {
            "type": 12,
            "content": {
              "version": "NotebookGroup/1.0",
              "groupType": "editable",
              "items": [
                {
                  "type": 1,
                  "content": {
                    "json": "ℹ️ Recommendations\r\n\r\n- Ensure that no service account are a member of the high privilege groups. Use RBAC to delegate the exact required permissions.\r\n- Limit the usage of nested group for administration.\r\n- Ensure that accounts are given only the required pernissions to execute their tasks.\r\n- Use just in time administration principle by adding users in a group only when they need the permissions, then remove them when their operation is over.\r\n- Limit the number of Organization management members. When you review the Admin Audit logs you might see that the administrators rarely needed Organization Management privileges.\r\n- Monitor the content of the following groups:\r\n  - TenantAdmins_-xxx (Membership in this role group is synchronized across services and managed centrally)\r\n  - Organization Management\r\n  - ExchangeServiceAdmins_-xxx (Membership in this role group is synchronized across services and managed centrally)\r\n  - Recipient Management (Member of this group have at least the following rights : set-mailbox, Add-MailboxPermission)\r\n  - Discovery Management\r\n  - Hygiene Management\r\n  - Security Administrator (Membership in this role group is synchronized across services and managed centrally)\r\n  - xxx High privilege group (not an exhaustive list)\r\n  - Compliance Management\r\n  - All RBAC groups that have high roles delegation\r\n  - All nested groups in high privileges groups\r\n  - Note that this is not a complete list. The content of all the groups that have high privileges should be monitored.\r\n- Each time a new RBAC group is created, decide if the content of this groups should be monitored\r\n- Periodically review the members of the groups",
                    "style": "info"
                  },
                  "conditionalVisibility": {
                    "parameterName": "Help",
                    "comparison": "isEqualTo",
                    "value": "Yes"
                  },
                  "name": "text - 0"
                },
                {
                  "type": 12,
                  "content": {
                    "version": "NotebookGroup/1.0",
                    "groupType": "editable",
                    "title": " Number of  direct members per group with RecipientType User",
                    "items": [
                      {
                        "type": 3,
                        "content": {
                          "version": "KqlItem/1.0",
                          "query": "ExchangeConfiguration(SpecificSectionList=\"RoleGroupMember\",SpecificConfigurationDate=\"{DateOfConfiguration:value}\",SpecificConfigurationEnv={EnvironmentList},Target = \"Online\")\r\n| project CmdletResultValue\r\n//| where CmdletResultValue.RecipientType !contains \"group\"\r\n| extend Members= tostring(CmdletResultValue.Identity)\r\n| summarize dcount(tostring(Members)) by RoleGroup = tostring(CmdletResultValue.RoleGroup)\r\n| where RoleGroup has_any (\"TenantAdmins\",\"Organization Management\", \"Discovery Management\", \"Compliance  Management\", \"Server Management\", \"ExchangeServiceAdmins\",\"Security Administrator\", \"SecurityAdmins\", \"Recipient Manangement\", \"Records Manangement\",\"Impersonation\",\"Export\")\r\n| sort by dcount_Members\r\n",
                          "size": 3,
                          "queryType": 0,
                          "resourceType": "microsoft.operationalinsights/workspaces",
                          "visualization": "tiles",
                          "tileSettings": {
                            "titleContent": {
                              "columnMatch": "RoleGroup",
                              "formatter": 1
                            },
                            "leftContent": {
                              "columnMatch": "dcount_Members",
                              "formatter": 12,
                              "formatOptions": {
                                "palette": "auto"
                              }
                            },
                            "showBorder": true,
                            "sortCriteriaField": "dcount_Members",
                            "sortOrderField": 2,
                            "size": "auto"
                          }
                        },
                        "name": "query - 0"
                      }
                    ]
                  },
                  "name": "ExchangeGroupsList"
                },
                {
                  "type": 12,
                  "content": {
                    "version": "NotebookGroup/1.0",
                    "groupType": "editable",
                    "title": "Number of  direct members per group with RecipientType User",
                    "expandable": true,
                    "items": [
                      {
                        "type": 3,
                        "content": {
                          "version": "KqlItem/1.0",
                          "query": "ExchangeConfiguration(SpecificSectionList=\"RoleGroupMember\",SpecificConfigurationDate=\"{DateOfConfiguration:value}\",SpecificConfigurationEnv={EnvironmentList},Target = \"Online\")\r\n| project CmdletResultValue\r\n| where CmdletResultValue.RecipientType !contains \"group\"\r\n| extend Members= tostring(CmdletResultValue.Identity)\r\n| summarize dcount(tostring(Members)) by RoleGroup = tostring(CmdletResultValue.RoleGroup)\r\n| sort by dcount_Members\r\n",
                          "size": 3,
                          "queryType": 0,
                          "resourceType": "microsoft.operationalinsights/workspaces",
                          "visualization": "tiles",
                          "tileSettings": {
                            "titleContent": {
                              "columnMatch": "RoleGroup",
                              "formatter": 1
                            },
                            "leftContent": {
                              "columnMatch": "dcount_Members",
                              "formatter": 12,
                              "formatOptions": {
                                "palette": "auto"
                              }
                            },
                            "showBorder": true,
                            "sortCriteriaField": "dcount_Members",
                            "sortOrderField": 2,
                            "size": "auto"
                          }
                        },
                        "name": "query - 0"
                      }
                    ]
                  },
                  "name": "ExchangeGroupsList - Copy"
                },
                {
                  "type": 1,
                  "content": {
                    "json": "Exchange Online groups content.\r\nSelect a group to display detailed information of its contents."
                  },
                  "name": "text - 2"
                },
                {
                  "type": 9,
                  "content": {
                    "version": "KqlParameterItem/1.0",
                    "parameters": [
                      {
                        "id": "b4b7a6ad-381a-48d6-9938-bf7cb812b474",
                        "version": "KqlParameterItem/1.0",
                        "name": "Group",
                        "type": 2,
                        "query": "ExchangeConfiguration(SpecificSectionList=\"RoleGroup\",SpecificConfigurationDate=\"{DateOfConfiguration:value}\",SpecificConfigurationEnv={EnvironmentList},Target = \"Online\")\r\n//| where CmdletResultValue.Parentgroup != \"Exchange Trusted Subsystem\"\r\n//| where CmdletResultValue.Parentgroup != \"Exchange Windows Permissions\"\r\n| project CmdletResultValue\r\n| extend GroupName = tostring(CmdletResultValue.Name)\r\n| distinct GroupName\r\n| sort by GroupName asc\r\n",
                        "typeSettings": {
                          "showDefault": false
                        },
                        "queryType": 0,
                        "resourceType": "microsoft.operationalinsights/workspaces",
                        "value": null
                      }
                    ],
                    "style": "pills",
                    "queryType": 0,
                    "resourceType": "microsoft.operationalinsights/workspaces"
                  },
                  "name": "parameters - 3"
                },
                {
                  "type": 3,
                  "content": {
                    "version": "KqlItem/1.0",
                    "query": "//ExchangeConfiguration(SpecificSectionList=\"ExGroup\",SpecificConfigurationDate=\"{DateOfConfiguration:value}\",SpecificConfigurationEnv={EnvironmentList},Target = \"Online\")\r\nExchangeConfiguration(SpecificSectionList=\"RoleGroupMember\",SpecificConfigurationDate=\"{DateOfConfiguration:value}\",SpecificConfigurationEnv={EnvironmentList},Target = \"Online\")\r\n| search CmdletResultValue.RoleGroup == \"{Group}\"\r\n//| where CmdletResultValue.Level != 0\r\n| project CmdletResultValue\r\n| extend Members = tostring(CmdletResultValue.Identity)\r\n//| extend Parentgroup = tostring(CmdletResultValue.Parentgroup)\r\n//| extend MemberPath = tostring(CmdletResultValue.MemberPath)\r\n//| extend Level = tostring(CmdletResultValue.Level)\r\n//| extend ObjectClass = tostring(CmdletResultValue.ObjectClass)\r\n//| extend LastLogon = CmdletResultValue.LastLogonString\r\n//| extend LastLogon = iif ( todatetime (CmdletResultValue.LastLogonString) < ago(-366d), CmdletResultValue.LastLogonString,strcat(\"💥\",CmdletResultValue.LastLogonString))\r\n//| extend LastPwdSet = CmdletResultValue.LastPwdSetString\r\n//| extend Enabled = tostring(CmdletResultValue.Enabled)\r\n| extend Members = case( CmdletResultValue.RecipientType == \"Group\", strcat( \"👪 \", Members), strcat( \"🧑‍🦰 \", Members) )\r\n| extend RecipientType = tostring(CmdletResultValue.RecipientType)",
                    "size": 3,
                    "showAnalytics": true,
                    "showExportToExcel": true,
                    "queryType": 0,
                    "resourceType": "microsoft.operationalinsights/workspaces",
                    "gridSettings": {
                      "formatters": [
                        {
                          "columnMatch": "CmdletResultValue",
                          "formatter": 5
                        }
                      ],
                      "rowLimit": 10000,
                      "filter": true
                    }
                  },
                  "name": "ExchangeServersGroupsGrid",
                  "styleSettings": {
                    "showBorder": true
                  }
                }
              ]
            },
            "name": "Exchange group"
          }
        ]
      },
      "conditionalVisibility": {
        "parameterName": "selected",
        "comparison": "isEqualTo",
        "value": "ExchAD"
      },
      "name": "Exchange and AD GRoup"
    },
    {
      "type": 12,
      "content": {
        "version": "NotebookGroup/1.0",
        "groupType": "editable",
        "title": "Transport Security configuration",
        "items": [
          {
            "type": 12,
            "content": {
              "version": "NotebookGroup/1.0",
              "groupType": "editable",
              "title": "Inbound Connector configuration",
              "items": [
                {
                  "type": 1,
                  "content": {
                    "json": "This section shows the configuration of the Inbound connnectors",
                    "style": "info"
                  },
                  "conditionalVisibility": {
                    "parameterName": "Help",
                    "comparison": "isEqualTo",
                    "value": "Yes"
                  },
                  "name": "TransportRulesHelp"
                },
                {
                  "type": 3,
                  "content": {
                    "version": "KqlItem/1.0",
                    "query": "ExchangeConfiguration(SpecificSectionList=\"InBoundC\",SpecificConfigurationDate=\"{DateOfConfiguration:value}\",SpecificConfigurationEnv={EnvironmentList},Target = \"Online\")\r\n| project CmdletResultValue\r\n| extend Name = tostring(CmdletResultValue.Name)\r\n| extend State = tostring(CmdletResultValue.Enabled)\r\n| extend ConnectorType = tostring(CmdletResultValue.ConnectorType)\r\n| extend ConnectorSource = tostring(CmdletResultValue.ConnectorSource)\r\n| extend SenderIPAddresses = tostring(CmdletResultValue.SenderIPAddresses)\r\n| extend SenderDomains = tostring(CmdletResultValue.SenderDomains)\r\n| extend TrustedOrganizations = tostring(CmdletResultValue.TrustedOrganizations)\r\n| extend AssociatedAcceptedDomainsRequireTls = tostring(CmdletResultValue.AssociatedAcceptedDomainsRequireTls)\r\n| extend RestrictDomainsToIPAddresses = tostring(CmdletResultValue.RestrictDomainsToIPAddresses)\r\n| extend RestrictDomainsToCertificate = tostring(CmdletResultValue.RestrictDomainsToCertificate)\r\n| extend CloudServicesMailEnabled = tostring(CmdletResultValue.CloudServicesMailEnabled)\r\n| extend TreatMessagesAsInternal = tostring(CmdletResultValue.TreatMessagesAsInternal)\r\n| extend TlsSenderCertificateName = tostring(CmdletResultValue.TlsSenderCertificateName)\r\n| extend ScanAndDropRecipients = tostring(CmdletResultValue.ScanAndDropRecipients)\r\n| extend Comment = tostring(CmdletResultValue.Comment)\r\n| extend WhenChanged = tostring(CmdletResultValue.WhenChanged)\r\n| extend WhenCreated = tostring(CmdletResultValue.WhenCreated)\r\n| project-away CmdletResultValue\r\n| sort  by Name asc",
                    "size": 3,
                    "showAnalytics": true,
                    "showExportToExcel": true,
                    "queryType": 0,
                    "resourceType": "microsoft.operationalinsights/workspaces"
                  },
                  "name": "query - 1",
                  "styleSettings": {
                    "showBorder": true
                  }
                },
                {
                  "type": 3,
                  "content": {
                    "version": "KqlItem/1.0",
                    "query": "let _EnvList ={EnvironmentList};\r\nlet _TypeEnv = \"Online\";\r\nlet _DateCompare = \"{DateCompare:value}\";\r\nlet _CurrentDate = \"{DateOfConfiguration:value}\";\r\nlet _DateCompareB = todatetime(_DateCompare);\r\nlet _currD = (ExchangeConfiguration(SpecificSectionList=\"InBoundC\",SpecificConfigurationDate=_CurrentDate,SpecificConfigurationEnv=_EnvList,Target = _TypeEnv)\r\n| summarize TimeMax = arg_max(TimeGenerated,*)\r\n| extend TimeMax = tostring(split(TimeMax,\"T\")[0])\r\n| project TimeMax);\r\nlet _CurrentDateB = todatetime(toscalar(_currD));\r\nlet BeforeData =  ExchangeConfiguration(SpecificSectionList=\"InBoundC\",SpecificConfigurationDate=_DateCompareB,SpecificConfigurationEnv=_EnvList,Target = _TypeEnv)\r\n    | extend Identity = tostring(CmdletResultValue.Identity)\r\n\t| extend State = tostring(CmdletResultValue.Enabled)\r\n\t| extend ConnectorType = tostring(CmdletResultValue.ConnectorType)\r\n\t| extend ConnectorSource = tostring(CmdletResultValue.ConnectorSource)\r\n\t| extend SenderIPAddresses = tostring(CmdletResultValue.SenderIPAddresses)\r\n\t| extend SenderDomains = tostring(CmdletResultValue.SenderDomains)\r\n\t| extend TrustedOrganizations = tostring(CmdletResultValue.TrustedOrganizations)\r\n\t| extend AssociatedAcceptedDomainsRequireTls = tostring(CmdletResultValue.AssociatedAcceptedDomainsRequireTls)\r\n\t| extend RestrictDomainsToIPAddresses = tostring(CmdletResultValue.RestrictDomainsToIPAddresses)\r\n\t| extend RestrictDomainsToCertificate = tostring(CmdletResultValue.RestrictDomainsToCertificate)\r\n\t| extend CloudServicesMailEnabled = tostring(CmdletResultValue.CloudServicesMailEnabled)\r\n\t| extend TreatMessagesAsInternal = tostring(CmdletResultValue.TreatMessagesAsInternal)\r\n\t| extend TlsSenderCertificateName = tostring(CmdletResultValue.TlsSenderCertificateName)\r\n\t| extend ScanAndDropRecipients = tostring(CmdletResultValue.ScanAndDropRecipients)\r\n\t| extend Comment = tostring(CmdletResultValue.Comment)\r\n    | extend WhenChanged = todatetime(WhenChanged)\r\n    | extend WhenCreated = todatetime(WhenCreated)\r\n;\r\nlet AfterData = \r\n     ExchangeConfiguration(SpecificSectionList=\"InBoundC\",SpecificConfigurationDate=_CurrentDate,SpecificConfigurationEnv=_EnvList,Target = _TypeEnv)\r\n   \t| extend Identity = tostring(CmdletResultValue.Identity)\r\n\t| extend State = tostring(CmdletResultValue.Enabled)\r\n\t| extend ConnectorType = tostring(CmdletResultValue.ConnectorType)\r\n\t| extend ConnectorSource = tostring(CmdletResultValue.ConnectorSource)\r\n\t| extend SenderIPAddresses = tostring(CmdletResultValue.SenderIPAddresses)\r\n\t| extend SenderDomains = tostring(CmdletResultValue.SenderDomains)\r\n\t| extend TrustedOrganizations = tostring(CmdletResultValue.TrustedOrganizations)\r\n\t| extend AssociatedAcceptedDomainsRequireTls = tostring(CmdletResultValue.AssociatedAcceptedDomainsRequireTls)\r\n\t| extend RestrictDomainsToIPAddresses = tostring(CmdletResultValue.RestrictDomainsToIPAddresses)\r\n\t| extend RestrictDomainsToCertificate = tostring(CmdletResultValue.RestrictDomainsToCertificate)\r\n\t| extend CloudServicesMailEnabled = tostring(CmdletResultValue.CloudServicesMailEnabled)\r\n\t| extend TreatMessagesAsInternal = tostring(CmdletResultValue.TreatMessagesAsInternal)\r\n\t| extend TlsSenderCertificateName = tostring(CmdletResultValue.TlsSenderCertificateName)\r\n\t| extend ScanAndDropRecipients = tostring(CmdletResultValue.ScanAndDropRecipients)\r\n\t| extend Comment = tostring(CmdletResultValue.Comment)\r\n    | extend WhenChanged = todatetime(WhenChanged)\r\n    | extend WhenCreated = todatetime(WhenCreated)\r\n;\r\nlet i=0;\r\nlet allDataRange = \r\n    ESIExchangeOnlineConfig_CL\r\n    | where TimeGenerated between (_DateCompareB .. _CurrentDateB)\r\n    | where ESIEnvironment_s == _EnvList\r\n    | where ExecutionResult_s <> \"EmptyResult\"\r\n    | where Section_s == \"InBoundC\"\r\n    | extend CmdletResultValue = parse_json(rawData_s)\r\n    | project TimeGenerated,CmdletResultValue,WhenChanged = todatetime(WhenChanged_t), WhenCreated=todatetime(WhenCreated_t)\r\n   \t| extend Identity = tostring(CmdletResultValue.Identity)\r\n\t| extend State = tostring(CmdletResultValue.Enabled)\r\n\t| extend ConnectorType = tostring(CmdletResultValue.ConnectorType)\r\n\t| extend ConnectorSource = tostring(CmdletResultValue.ConnectorSource)\r\n\t| extend SenderIPAddresses = tostring(CmdletResultValue.SenderIPAddresses)\r\n\t| extend SenderDomains = tostring(CmdletResultValue.SenderDomains)\r\n\t| extend TrustedOrganizations = tostring(CmdletResultValue.TrustedOrganizations)\r\n\t| extend AssociatedAcceptedDomainsRequireTls = tostring(CmdletResultValue.AssociatedAcceptedDomainsRequireTls)\r\n\t| extend RestrictDomainsToIPAddresses = tostring(CmdletResultValue.RestrictDomainsToIPAddresses)\r\n\t| extend RestrictDomainsToCertificate = tostring(CmdletResultValue.RestrictDomainsToCertificate)\r\n\t| extend CloudServicesMailEnabled = tostring(CmdletResultValue.CloudServicesMailEnabled)\r\n\t| extend TreatMessagesAsInternal = tostring(CmdletResultValue.TreatMessagesAsInternal)\r\n\t| extend TlsSenderCertificateName = tostring(CmdletResultValue.TlsSenderCertificateName)\r\n\t| extend ScanAndDropRecipients = tostring(CmdletResultValue.ScanAndDropRecipients)\r\n\t| extend Comment = tostring(CmdletResultValue.Comment)\r\n    ;\r\nlet DiffAddDataP1 = allDataRange\r\n  | join kind = rightanti  (AfterData | where WhenCreated >=_DateCompareB) on WhenCreated\r\n;\r\nlet DiffAddDataP2 = allDataRange\r\n    | join kind = innerunique   (allDataRange ) on WhenCreated\r\n    | where WhenCreated >=_DateCompareB\r\n    | where bin(WhenCreated,5m)==bin(WhenChanged,5m)\r\n    | distinct  Identity,State,ConnectorType,ConnectorSource,SenderIPAddresses,SenderDomains,TrustedOrganizations,AssociatedAcceptedDomainsRequireTls,RestrictDomainsToIPAddresses,RestrictDomainsToCertificate,CloudServicesMailEnabled,TreatMessagesAsInternal,TlsSenderCertificateName,ScanAndDropRecipients,Comment,WhenChanged,WhenCreated\r\n ;\r\nlet DiffAddData = union DiffAddDataP1,DiffAddDataP2\r\n| extend Actiontype =\"Add\";\r\nlet DiffRemoveData = allDataRange\r\n    | join kind = leftanti AfterData on Identity\r\n    | extend Actiontype =\"Remove\"\r\n    | distinct  Actiontype ,Identity,State,ConnectorType,ConnectorSource,SenderIPAddresses,SenderDomains,TrustedOrganizations,AssociatedAcceptedDomainsRequireTls,RestrictDomainsToIPAddresses,RestrictDomainsToCertificate,CloudServicesMailEnabled,TreatMessagesAsInternal,TlsSenderCertificateName,ScanAndDropRecipients,Comment,WhenCreated\r\n    | project  WhenChanged=_CurrentDateB,Actiontype,Identity,State,ConnectorType,ConnectorSource,SenderIPAddresses,SenderDomains,TrustedOrganizations,AssociatedAcceptedDomainsRequireTls,RestrictDomainsToIPAddresses,RestrictDomainsToCertificate,CloudServicesMailEnabled,TreatMessagesAsInternal,TlsSenderCertificateName,ScanAndDropRecipients,Comment,WhenCreated\r\n    ;\r\nlet DiffModifData = union AfterData,allDataRange\r\n| sort by Identity,WhenChanged asc\r\n| project WhenChanged,Identity,State,ConnectorType,ConnectorSource,SenderIPAddresses,SenderDomains,TrustedOrganizations,AssociatedAcceptedDomainsRequireTls,RestrictDomainsToIPAddresses,RestrictDomainsToCertificate,CloudServicesMailEnabled,TreatMessagesAsInternal,TlsSenderCertificateName,ScanAndDropRecipients,Comment,WhenCreated\r\n| extend Identity = iff( Identity == prev(Identity) and Identity != prev(Identity) and prev(Identity) !=\"\" , strcat(\"📍 \", Identity, \" (\",prev(Identity),\"->\", Identity,\" )\"),Identity)\r\n| extend State = iff( Identity == prev(Identity) and State != prev(State) and prev(State) !=\"\" , strcat(\"📍 \", State, \" (\",prev(State),\"->\", State,\" )\"),State)\r\n| extend ConnectorType = iff( Identity == prev(Identity) and ConnectorType != prev(ConnectorType) and prev(ConnectorType) !=\"\" , strcat(\"📍 \", ConnectorType, \" (\",prev(ConnectorType),\"->\", ConnectorType,\" )\"),ConnectorType)\r\n| extend ConnectorSource = iff( Identity == prev(Identity) and ConnectorSource != prev(ConnectorSource) and prev(ConnectorSource) !=\"\" , strcat(\"📍 \", ConnectorSource, \" (\",prev(ConnectorSource),\"->\", ConnectorSource,\" )\"),ConnectorSource)\r\n| extend SenderIPAddresses = iff( Identity == prev(Identity) and SenderIPAddresses != prev(SenderIPAddresses) and prev(SenderIPAddresses) !=\"\" , strcat(\"📍 \", SenderIPAddresses, \" (\",prev(SenderIPAddresses),\"->\", SenderIPAddresses,\" )\"),SenderIPAddresses)\r\n| extend SenderDomains = iff( Identity == prev(Identity) and SenderDomains != prev(SenderDomains) and prev(SenderDomains) !=\"\" , strcat(\"📍 \", SenderDomains, \" (\",prev(SenderDomains),\"->\", SenderDomains,\" )\"),SenderDomains)\r\n| extend TrustedOrganizations = iff( Identity == prev(Identity) and TrustedOrganizations != prev(TrustedOrganizations) and prev(TrustedOrganizations) !=\"\" , strcat(\"📍 \", TrustedOrganizations, \" (\",prev(TrustedOrganizations),\"->\", TrustedOrganizations,\" )\"),TrustedOrganizations)\r\n| extend AssociatedAcceptedDomainsRequireTls = iff (Identity == prev(Identity) and AssociatedAcceptedDomainsRequireTls != prev(AssociatedAcceptedDomainsRequireTls) and prev(AssociatedAcceptedDomainsRequireTls) !=\"\" , strcat(\"📍 \", AssociatedAcceptedDomainsRequireTls, \" (\",prev(AssociatedAcceptedDomainsRequireTls),\"->\", AssociatedAcceptedDomainsRequireTls,\" )\"),AssociatedAcceptedDomainsRequireTls)\r\n| extend RestrictDomainsToIPAddresses = iff(Identity == prev(Identity) and RestrictDomainsToIPAddresses != prev(RestrictDomainsToIPAddresses) and prev(RestrictDomainsToIPAddresses) !=\"\" , strcat(\"📍 \", RestrictDomainsToIPAddresses, \" (\",prev(RestrictDomainsToIPAddresses),\"->\", RestrictDomainsToIPAddresses,\" )\"),RestrictDomainsToIPAddresses)\r\n| extend RestrictDomainsToCertificate = iff( Identity == prev(Identity) and RestrictDomainsToCertificate != prev(RestrictDomainsToCertificate) and prev(RestrictDomainsToCertificate) !=\"\" , strcat(\"📍 \", RestrictDomainsToCertificate, \" (\",prev(RestrictDomainsToCertificate),\"->\", RestrictDomainsToCertificate,\" )\"),RestrictDomainsToCertificate)\r\n| extend CloudServicesMailEnabled = iff( Identity == prev(Identity) and CloudServicesMailEnabled != prev(CloudServicesMailEnabled) and prev(CloudServicesMailEnabled) !=\"\" , strcat(\"📍 \", CloudServicesMailEnabled, \" (\",prev(CloudServicesMailEnabled),\"->\", CloudServicesMailEnabled,\" )\"),CloudServicesMailEnabled)\r\n| extend TreatMessagesAsInternal = iff( Identity == prev(Identity) and TreatMessagesAsInternal != prev(TreatMessagesAsInternal) and prev(TreatMessagesAsInternal) !=\"\" , strcat(\"📍 \", TreatMessagesAsInternal, \" (\",prev(TreatMessagesAsInternal),\"->\", TreatMessagesAsInternal,\" )\"),TreatMessagesAsInternal)\r\n| extend TlsSenderCertificateName = iff(Identity == prev(Identity) and TlsSenderCertificateName != prev(TlsSenderCertificateName) and prev(TlsSenderCertificateName) !=\"\" , strcat(\"📍 \", TlsSenderCertificateName, \" (\",prev(TlsSenderCertificateName),\"->\", TlsSenderCertificateName,\" )\"),TlsSenderCertificateName)\r\n| extend ScanAndDropRecipients = iff( Identity == prev(Identity) and ScanAndDropRecipients != prev(ScanAndDropRecipients) and prev(ScanAndDropRecipients) !=\"\" , strcat(\"📍 \", ScanAndDropRecipients, \" (\",prev(ScanAndDropRecipients),\"->\", ScanAndDropRecipients,\" )\"),ScanAndDropRecipients)\r\n| extend Comment = iff( Identity == prev(Identity) and Comment != prev(Comment) and prev(Comment) !=\"\" , strcat(\"📍 \", Comment, \" (\",prev(Comment),\"->\", Comment,\" )\"),Comment)\r\n| extend ActiontypeR =iff((Identity contains \"📍\" or State contains \"📍\" or ConnectorType contains \"📍\" or ConnectorSource contains \"📍\" or SenderIPAddresses contains \"📍\" or SenderDomains contains \"📍\" or TrustedOrganizations contains \"📍\" or AssociatedAcceptedDomainsRequireTls contains \"📍\" or RestrictDomainsToIPAddresses contains \"📍\" or RestrictDomainsToCertificate contains \"📍\" or CloudServicesMailEnabled contains \"📍\" or  TreatMessagesAsInternal contains \"📍\" or TlsSenderCertificateName contains \"📍\" or ScanAndDropRecipients contains \"📍\" or Comment contains \"📍\" ), i=i + 1, i)\r\n| extend Actiontype =iff(ActiontypeR > 0, \"Modif\", \"NO\")\r\n| where ActiontypeR == 1\r\n| project WhenChanged,Actiontype,Identity,State,ConnectorType,ConnectorSource,SenderIPAddresses,SenderDomains,TrustedOrganizations,AssociatedAcceptedDomainsRequireTls,RestrictDomainsToIPAddresses,RestrictDomainsToCertificate,CloudServicesMailEnabled,TreatMessagesAsInternal,TlsSenderCertificateName,ScanAndDropRecipients,Comment,WhenCreated\r\n;\r\nunion DiffAddData, DiffRemoveData, DiffModifData\r\n| extend WhenChanged = iff (Actiontype == \"Modif\", WhenChanged, iff(Actiontype == \"Add\",WhenCreated, WhenChanged))\r\n| extend Actiontype = case(Actiontype == \"Add\", strcat(\"➕ \", Actiontype), Actiontype == \"Remove\", strcat(\"➖ \", Actiontype), Actiontype == \"Modif\", strcat(\"📍 \", Actiontype), \"N/A\")\r\n| sort by WhenChanged desc \r\n| project\r\n    WhenChanged,\r\n    Actiontype,\r\n    Identity,\r\n    State,\r\n    ConnectorType,\r\n    ConnectorSource,\r\n    Comment,\r\n    SenderIPAddresses,\r\n    SenderDomains,\r\n    TrustedOrganizations,\r\n    AssociatedAcceptedDomainsRequireTls,\r\n    RestrictDomainsToIPAddresses,\r\n    RestrictDomainsToCertificate,\r\n    CloudServicesMailEnabled,\r\n    TreatMessagesAsInternal,\r\n    TlsSenderCertificateName,\r\n    ScanAndDropRecipients,\r\n    WhenCreated",
                    "size": 3,
                    "showAnalytics": true,
                    "title": "Display changes ( Add, Remove, modifications of parameters )",
                    "showExportToExcel": true,
                    "queryType": 0,
                    "resourceType": "microsoft.operationalinsights/workspaces",
                    "gridSettings": {
                      "hierarchySettings": {
                        "treeType": 1,
                        "groupBy": [
                          "Identity"
                        ],
                        "expandTopLevel": true
                      }
                    }
                  },
                  "conditionalVisibility": {
                    "parameterName": "Compare_Collect",
                    "comparison": "isEqualTo",
                    "value": "True"
                  },
                  "name": "query - 2"
                }
              ]
            },
            "name": "Inbound Connector configuration"
          },
          {
            "type": 12,
            "content": {
              "version": "NotebookGroup/1.0",
              "groupType": "editable",
              "title": "Outbound Connector configuration",
              "items": [
                {
                  "type": 1,
                  "content": {
                    "json": "This section shows the configuration of the Outbound connnectors",
                    "style": "info"
                  },
                  "conditionalVisibility": {
                    "parameterName": "Help",
                    "comparison": "isEqualTo",
                    "value": "Yes"
                  },
                  "name": "TransportRulesHelp"
                },
                {
                  "type": 3,
                  "content": {
                    "version": "KqlItem/1.0",
                    "query": "ExchangeConfiguration(SpecificSectionList=\"OutBoundC\",SpecificConfigurationDate=\"{DateOfConfiguration:value}\",SpecificConfigurationEnv={EnvironmentList},Target = \"Online\")\r\n| project CmdletResultValue\r\n| extend Name = tostring(CmdletResultValue.Name)\r\n| extend State = tostring(CmdletResultValue.Enabled)\r\n| extend UseMXRecord = tostring(CmdletResultValue.UseMXRecord)\r\n| extend ConnectorType = tostring(CmdletResultValue.ConnectorType)\r\n| extend ConnectorSource = tostring(CmdletResultValue.ConnectorSource)\r\n| extend RecipientDomains = tostring(CmdletResultValue.RecipientDomains)\r\n| extend SmartHosts = tostring(CmdletResultValue.SmartHosts)\r\n| extend TlsDomain = tostring(CmdletResultValue.TlsDomain)\r\n| extend TlsSettings = tostring(CmdletResultValue.TlsSettings)\r\n| extend IsTransportRuleScoped = tostring(CmdletResultValue.IsTransportRuleScoped)\r\n| extend RouteAllMessagesViaOnPremises = tostring(CmdletResultValue.RouteAllMessagesViaOnPremises)\r\n| extend CloudServicesMailEnabled = tostring(CmdletResultValue.CloudServicesMailEnabled)\r\n| extend AllAcceptedDomains = tostring(CmdletResultValue.AllAcceptedDomains)\r\n| extend SenderRewritingEnabled = tostring(CmdletResultValue.SenderRewritingEnabled)\r\n| extend TestMode = tostring(CmdletResultValue.TestMode)\r\n| extend LinkForModifiedConnector = tostring(CmdletResultValue.LinkForModifiedConnector)\r\n| extend ValidationRecipients = tostring(CmdletResultValue.ValidationRecipients)\r\n| extend IsValidated = tostring(CmdletResultValue.IsValidated)\r\n| extend LastValidationTimestamp = tostring(CmdletResultValue.LastValidationTimestamp)\r\n| extend Comment = tostring(CmdletResultValue.Comment)\r\n| extend WhenChanged = tostring(CmdletResultValue.WhenChanged)\r\n| extend WhenCreated = tostring(CmdletResultValue.WhenCreated)\r\n| project-away CmdletResultValue\r\n| sort  by Name asc",
                    "size": 3,
                    "showAnalytics": true,
                    "showExportToExcel": true,
                    "queryType": 0,
                    "resourceType": "microsoft.operationalinsights/workspaces"
                  },
                  "name": "query - 1",
                  "styleSettings": {
                    "showBorder": true
                  }
                }
              ]
            },
            "name": "Outbound Connector configuration - Copy"
          },
          {
            "type": 3,
            "content": {
              "version": "KqlItem/1.0",
              "query": "let _EnvList ={EnvironmentList};\r\nlet _TypeEnv = \"Online\";\r\nlet _DateCompare = \"{DateCompare:value}\";\r\nlet _CurrentDate = \"{DateOfConfiguration:value}\";\r\nlet _DateCompareB = todatetime(_DateCompare);\r\nlet _currD = (ExchangeConfiguration(SpecificSectionList=\"OutBoundC\",SpecificConfigurationDate=_CurrentDate,SpecificConfigurationEnv=_EnvList,Target = _TypeEnv)\r\n| summarize TimeMax = arg_max(TimeGenerated,*)\r\n| extend TimeMax = tostring(split(TimeMax,\"T\")[0])\r\n| project TimeMax);\r\nlet _CurrentDateB = todatetime(toscalar(_currD));\r\nlet BeforeData =  ExchangeConfiguration(SpecificSectionList=\"OutBoundC\",SpecificConfigurationDate=_DateCompareB,SpecificConfigurationEnv=_EnvList,Target = _TypeEnv)\r\n    | extend Identity = tostring(CmdletResultValue.Identity)\r\n\t| extend State = tostring(CmdletResultValue.Enabled)\r\n    | extend UseMXRecord = tostring(CmdletResultValue.UseMXRecord)\r\n\t| extend ConnectorType = tostring(CmdletResultValue.ConnectorType)\r\n\t| extend ConnectorSource = tostring(CmdletResultValue.ConnectorSource)\r\n\t| extend RecipientDomains = tostring(CmdletResultValue.RecipientDomains)\r\n    | extend SmartHosts = tostring(CmdletResultValue.SmartHosts)\r\n    | extend TlsDomain = tostring(CmdletResultValue.TlsDomain)\r\n    | extend TlsSettings = tostring(CmdletResultValue.TlsSettings)\r\n    | extend IsTransportRuleScoped = tostring(CmdletResultValue.IsTransportRuleScoped)\r\n    | extend RouteAllMessagesViaOnPremises = tostring(CmdletResultValue.RouteAllMessagesViaOnPremises)\r\n    | extend CloudServicesMailEnabled = tostring(CmdletResultValue.CloudServicesMailEnabled)\r\n    | extend AllAcceptedDomains = tostring(CmdletResultValue.AllAcceptedDomains)\r\n    | extend SenderRewritingEnabled = tostring(CmdletResultValue.SenderRewritingEnabled)\r\n    | extend TestMode = tostring(CmdletResultValue.TestMode)\r\n    | extend LinkForModifiedConnector = tostring(CmdletResultValue.LinkForModifiedConnector)\r\n    | extend ValidationRecipients = tostring(CmdletResultValue.ValidationRecipients)\r\n    | extend IsValidated = tostring(CmdletResultValue.IsValidated)\r\n    | extend LastValidationTimestamp = tostring(CmdletResultValue.LastValidationTimestamp)\r\n    | extend Comment = tostring(CmdletResultValue.Comment)\r\n    | extend WhenChanged = todatetime(WhenChanged)\r\n    | extend WhenCreated = todatetime(WhenCreated)\r\n;\r\nlet AfterData = \r\n     ExchangeConfiguration(SpecificSectionList=\"OutBoundC\",SpecificConfigurationDate=_CurrentDate,SpecificConfigurationEnv=_EnvList,Target = _TypeEnv)\r\n    | extend Identity = tostring(CmdletResultValue.Identity)\r\n\t| extend State = tostring(CmdletResultValue.Enabled)\r\n    | extend UseMXRecord = tostring(CmdletResultValue.UseMXRecord)\r\n\t| extend ConnectorType = tostring(CmdletResultValue.ConnectorType)\r\n\t| extend ConnectorSource = tostring(CmdletResultValue.ConnectorSource)\r\n\t| extend RecipientDomains = tostring(CmdletResultValue.RecipientDomains)\r\n    | extend SmartHosts = tostring(CmdletResultValue.SmartHosts)\r\n    | extend TlsDomain = tostring(CmdletResultValue.TlsDomain)\r\n    | extend TlsSettings = tostring(CmdletResultValue.TlsSettings)\r\n    | extend IsTransportRuleScoped = tostring(CmdletResultValue.IsTransportRuleScoped)\r\n    | extend RouteAllMessagesViaOnPremises = tostring(CmdletResultValue.RouteAllMessagesViaOnPremises)\r\n    | extend CloudServicesMailEnabled = tostring(CmdletResultValue.CloudServicesMailEnabled)\r\n    | extend AllAcceptedDomains = tostring(CmdletResultValue.AllAcceptedDomains)\r\n    | extend SenderRewritingEnabled = tostring(CmdletResultValue.SenderRewritingEnabled)\r\n    | extend TestMode = tostring(CmdletResultValue.TestMode)\r\n    | extend LinkForModifiedConnector = tostring(CmdletResultValue.LinkForModifiedConnector)\r\n    | extend ValidationRecipients = tostring(CmdletResultValue.ValidationRecipients)\r\n    | extend IsValidated = tostring(CmdletResultValue.IsValidated)\r\n    | extend LastValidationTimestamp = tostring(CmdletResultValue.LastValidationTimestamp)\r\n    | extend Comment = tostring(CmdletResultValue.Comment)\r\n    | extend WhenChanged = todatetime(WhenChanged)\r\n    | extend WhenCreated = todatetime(WhenCreated)\r\n;\r\nlet i=0;\r\nlet allDataRange = \r\n    ESIExchangeOnlineConfig_CL\r\n    | where TimeGenerated between (_DateCompareB .. _CurrentDateB)\r\n    | where ESIEnvironment_s == _EnvList\r\n    | where ExecutionResult_s <> \"EmptyResult\"\r\n    | where Section_s == \"OutBoundC\"\r\n    | extend CmdletResultValue = parse_json(rawData_s)\r\n    | project TimeGenerated,CmdletResultValue,WhenChanged = todatetime(WhenChanged_t), WhenCreated=todatetime(WhenCreated_t)\r\n   \t| extend Identity = tostring(CmdletResultValue.Identity)\r\n\t| extend State = tostring(CmdletResultValue.Enabled)\r\n    | extend UseMXRecord = tostring(CmdletResultValue.UseMXRecord)\r\n\t| extend ConnectorType = tostring(CmdletResultValue.ConnectorType)\r\n\t| extend ConnectorSource = tostring(CmdletResultValue.ConnectorSource)\r\n\t| extend RecipientDomains = tostring(CmdletResultValue.RecipientDomains)\r\n    | extend SmartHosts = tostring(CmdletResultValue.SmartHosts)\r\n    | extend TlsDomain = tostring(CmdletResultValue.TlsDomain)\r\n    | extend TlsSettings = tostring(CmdletResultValue.TlsSettings)\r\n    | extend IsTransportRuleScoped = tostring(CmdletResultValue.IsTransportRuleScoped)\r\n    | extend RouteAllMessagesViaOnPremises = tostring(CmdletResultValue.RouteAllMessagesViaOnPremises)\r\n    | extend CloudServicesMailEnabled = tostring(CmdletResultValue.CloudServicesMailEnabled)\r\n    | extend AllAcceptedDomains = tostring(CmdletResultValue.AllAcceptedDomains)\r\n    | extend SenderRewritingEnabled = tostring(CmdletResultValue.SenderRewritingEnabled)\r\n    | extend TestMode = tostring(CmdletResultValue.TestMode)\r\n    | extend LinkForModifiedConnector = tostring(CmdletResultValue.LinkForModifiedConnector)\r\n    | extend ValidationRecipients = tostring(CmdletResultValue.ValidationRecipients)\r\n    | extend IsValidated = tostring(CmdletResultValue.IsValidated)\r\n    | extend LastValidationTimestamp = tostring(CmdletResultValue.LastValidationTimestamp)\r\n    | extend Comment = tostring(CmdletResultValue.Comment)\r\n    ;\r\nlet DiffAddDataP1 = allDataRange\r\n  | join kind = rightanti  (AfterData | where WhenCreated >=_DateCompareB) on WhenCreated\r\n;\r\nlet DiffAddDataP2 = allDataRange\r\n    | join kind = innerunique   (allDataRange ) on WhenCreated\r\n    | where WhenCreated >=_DateCompareB\r\n    | where bin(WhenCreated,5m)==bin(WhenChanged,5m)\r\n    | distinct  Identity,State,ConnectorType,ConnectorSource,UseMXRecord,RecipientDomains,SmartHosts,TlsDomain,TlsSettings,IsTransportRuleScoped,RouteAllMessagesViaOnPremises,CloudServicesMailEnabled,AllAcceptedDomains,SenderRewritingEnabled,TestMode,LinkForModifiedConnector,ValidationRecipients,IsValidated,LastValidationTimestamp,Comment,WhenCreated\r\n ;\r\nlet DiffAddData = union DiffAddDataP1,DiffAddDataP2\r\n| extend Actiontype =\"Add\";\r\nlet DiffRemoveData = allDataRange\r\n    | join kind = leftanti AfterData on Identity\r\n    | extend Actiontype =\"Remove\"\r\n    | distinct  Actiontype ,Identity,State,ConnectorType,ConnectorSource,UseMXRecord,RecipientDomains,SmartHosts,TlsDomain,TlsSettings,IsTransportRuleScoped,RouteAllMessagesViaOnPremises,CloudServicesMailEnabled,AllAcceptedDomains,SenderRewritingEnabled,TestMode,LinkForModifiedConnector,ValidationRecipients,IsValidated,LastValidationTimestamp,Comment,WhenCreated\r\n    | project  WhenChanged=_CurrentDateB,Actiontype,Identity,State,ConnectorType,ConnectorSource,UseMXRecord,RecipientDomains,SmartHosts,TlsDomain,TlsSettings,IsTransportRuleScoped,RouteAllMessagesViaOnPremises,CloudServicesMailEnabled,AllAcceptedDomains,SenderRewritingEnabled,TestMode,LinkForModifiedConnector,ValidationRecipients,IsValidated,LastValidationTimestamp,Comment,WhenCreated\r\n    ;\r\nlet DiffModifData = union AfterData,allDataRange\r\n| sort by Identity,WhenChanged asc\r\n| project WhenChanged,Identity,State,ConnectorType,ConnectorSource,UseMXRecord,RecipientDomains,SmartHosts,TlsDomain,TlsSettings,IsTransportRuleScoped,RouteAllMessagesViaOnPremises,CloudServicesMailEnabled,AllAcceptedDomains,SenderRewritingEnabled,TestMode,LinkForModifiedConnector,ValidationRecipients,IsValidated,LastValidationTimestamp,Comment,WhenCreated\r\n| extend Identity = iff( Identity == prev(Identity) and Identity != prev(Identity) and prev(Identity) !=\"\" , strcat(\"📍 \", Identity, \" (\",prev(Identity),\"->\", Identity,\" )\"),Identity)\r\n| extend State = iff( Identity == prev(Identity) and State != prev(State) and prev(State) !=\"\" , strcat(\"📍 \", State, \" (\",prev(State),\"->\", State,\" )\"),State)\r\n| extend ConnectorType = iff( Identity == prev(Identity) and ConnectorType != prev(ConnectorType) and prev(ConnectorType) !=\"\" , strcat(\"📍 \", ConnectorType, \" (\",prev(ConnectorType),\"->\", ConnectorType,\" )\"),ConnectorType)\r\n| extend ConnectorSource = iff( Identity == prev(Identity) and ConnectorSource != prev(ConnectorSource) and prev(ConnectorSource) !=\"\" , strcat(\"📍 \", ConnectorSource, \" (\",prev(ConnectorSource),\"->\", ConnectorSource,\" )\"),ConnectorSource)\r\n| extend CloudServicesMailEnabled = iff( Identity == prev(Identity) and CloudServicesMailEnabled != prev(CloudServicesMailEnabled) and prev(CloudServicesMailEnabled) !=\"\" , strcat(\"📍 \", CloudServicesMailEnabled, \" (\",prev(CloudServicesMailEnabled),\"->\", CloudServicesMailEnabled,\" )\"),CloudServicesMailEnabled)\r\n| extend Comment = iff( Comment == prev(Comment) and Comment != prev(Comment) and prev(Comment) !=\"\" , strcat(\"📍 \", Comment, \" (\",prev(Comment),\"->\", Comment,\" )\"),Comment)\r\n| extend RecipientDomains = iff( Identity == prev(Identity) and RecipientDomains != prev(RecipientDomains) and prev(RecipientDomains) !=\"\" , strcat(\"📍 \", RecipientDomains, \" (\",prev(RecipientDomains),\"->\", RecipientDomains,\" )\"),RecipientDomains)\r\n| extend SmartHosts = iff( Identity == prev(Identity) and SmartHosts != prev(SmartHosts) and prev(SmartHosts) !=\"\" , strcat(\"📍 \", SmartHosts, \" (\",prev(SmartHosts),\"->\", SmartHosts,\" )\"),SmartHosts)\r\n| extend TlsDomain = iff( Identity == prev(Identity) and TlsDomain != prev(TlsDomain) and prev(TlsDomain) !=\"\" , strcat(\"📍 \", TlsDomain, \" (\",prev(TlsDomain),\"->\", TlsDomain,\" )\"),TlsDomain)\r\n| extend IsTransportRuleScoped = iff( Identity == prev(Identity) and IsTransportRuleScoped != prev(IsTransportRuleScoped) and prev(IsTransportRuleScoped) !=\"\" , strcat(\"📍 \", IsTransportRuleScoped, \" (\",prev(IsTransportRuleScoped),\"->\", IsTransportRuleScoped,\" )\"),IsTransportRuleScoped)\r\n| extend RouteAllMessagesViaOnPremises = iff( Identity == prev(Identity) and RouteAllMessagesViaOnPremises != prev(RouteAllMessagesViaOnPremises) and prev(RouteAllMessagesViaOnPremises) !=\"\" , strcat(\"📍 \", RouteAllMessagesViaOnPremises, \" (\",prev(RouteAllMessagesViaOnPremises),\"->\", RouteAllMessagesViaOnPremises,\" )\"),RouteAllMessagesViaOnPremises)\r\n| extend AllAcceptedDomains = iff( Identity == prev(Identity) and AllAcceptedDomains != prev(AllAcceptedDomains) and prev(AllAcceptedDomains) !=\"\" , strcat(\"📍 \", AllAcceptedDomains, \" (\",prev(AllAcceptedDomains),\"->\", AllAcceptedDomains,\" )\"),AllAcceptedDomains)\r\n| extend SenderRewritingEnabled = iff( Identity == prev(Identity) and SenderRewritingEnabled != prev(SenderRewritingEnabled) and prev(SenderRewritingEnabled) !=\"\" , strcat(\"📍 \", SenderRewritingEnabled, \" (\",prev(SenderRewritingEnabled),\"->\", SenderRewritingEnabled,\" )\"),SenderRewritingEnabled)\r\n| extend TestMode = iff( Identity == prev(Identity)and TestMode != prev(TestMode) and prev(TestMode) !=\"\" , strcat(\"📍 \", TestMode, \" (\",prev(TestMode),\"->\", TestMode,\" )\"),TestMode)\r\n| extend LinkForModifiedConnector = iff( Identity == prev(Identity) and LinkForModifiedConnector != prev(LinkForModifiedConnector) and prev(LinkForModifiedConnector) !=\"\" , strcat(\"📍 \", LinkForModifiedConnector, \" (\",prev(LinkForModifiedConnector),\"->\", LinkForModifiedConnector,\" )\"),LinkForModifiedConnector)\r\n| extend ValidationRecipients = iff( Identity == prev(Identity) and ValidationRecipients != prev(ValidationRecipients) and prev(ValidationRecipients) !=\"\" , strcat(\"📍 \", ValidationRecipients, \" (\",prev(ValidationRecipients),\"->\", ValidationRecipients,\" )\"),ValidationRecipients)\r\n| extend IsValidated = iff( Identity == prev(Identity) and IsValidated != prev(IsValidated) and prev(IsValidated) !=\"\" , strcat(\"📍 \", IsValidated, \" (\",prev(IsValidated),\"->\", IsValidated,\" )\"),IsValidated)\r\n| extend LastValidationTimestamp = iff( Identity == prev(Identity) and LastValidationTimestamp != prev(LastValidationTimestamp) and prev(LastValidationTimestamp) !=\"\" , strcat(\"📍 \", LastValidationTimestamp, \" (\",prev(LastValidationTimestamp),\"->\", LastValidationTimestamp,\" )\"),LastValidationTimestamp)\r\n| extend Comment = iff( Identity == prev(Identity) and Comment != prev(Comment) and prev(Comment) !=\"\" , strcat(\"📍 \", Comment, \" (\",prev(Comment),\"->\", Comment,\" )\"),Comment)\r\n| extend ActiontypeR =iff((Identity contains \"📍\" or State contains \"📍\" or ConnectorType contains \"📍\" or ConnectorSource contains \"📍\"or CloudServicesMailEnabled contains \"📍\"  or Comment contains \"📍\" or UseMXRecord contains \"📍\" or RecipientDomains contains \"📍\" or SmartHosts contains \"📍\" or TlsDomain contains \"📍\" or TlsSettings contains \"📍\" or IsTransportRuleScoped contains \"📍\" or RouteAllMessagesViaOnPremises contains \"📍\" or AllAcceptedDomains contains \"📍\" or SenderRewritingEnabled contains \"📍\" or TestMode contains \"📍\" or LinkForModifiedConnector  contains \"📍\" or ValidationRecipients contains \"📍\" or IsValidated contains \"📍\" or LastValidationTimestamp contains \"📍\" ), i=i + 1, i)\r\n| extend Actiontype =iff(ActiontypeR > 0, \"Modif\", \"NO\")\r\n| where ActiontypeR == 1\r\n| project WhenChanged,Actiontype,Identity,State,ConnectorType,ConnectorSource,UseMXRecord,RecipientDomains,SmartHosts,TlsDomain,TlsSettings,IsTransportRuleScoped,RouteAllMessagesViaOnPremises,CloudServicesMailEnabled,AllAcceptedDomains,SenderRewritingEnabled,TestMode,LinkForModifiedConnector,ValidationRecipients,IsValidated,LastValidationTimestamp,Comment,WhenCreated\r\n;\r\nunion DiffAddData, DiffRemoveData, DiffModifData\r\n| extend WhenChanged = iff (Actiontype == \"Modif\", WhenChanged, iff(Actiontype == \"Add\",WhenCreated, WhenChanged))\r\n| extend Actiontype = case(Actiontype == \"Add\", strcat(\"➕ \", Actiontype), Actiontype == \"Remove\", strcat(\"➖ \", Actiontype), Actiontype == \"Modif\", strcat(\"📍 \", Actiontype), \"N/A\")\r\n| sort by WhenChanged desc \r\n| project\r\n    WhenChanged,\r\n    Actiontype,\r\n    Identity,\r\n    State,\r\n    ConnectorType,\r\n    ConnectorSource,  \r\n    CloudServicesMailEnabled,\r\n    Comment,\r\n    UseMXRecord,\r\n    RecipientDomains,\r\n    SmartHosts,\r\n    TlsDomain,\r\n    TlsSettings,\r\n    IsTransportRuleScoped,\r\n    RouteAllMessagesViaOnPremises,\r\n    AllAcceptedDomains,\r\n    SenderRewritingEnabled,\r\n    TestMode,\r\n    LinkForModifiedConnector,\r\n    ValidationRecipients,\r\n    IsValidated,\r\n    LastValidationTimestamp,\r\n    WhenCreated",
              "size": 3,
              "showAnalytics": true,
              "title": "Display changes ( Add, Remove, modifications of parameters )",
              "showExportToExcel": true,
              "queryType": 0,
              "resourceType": "microsoft.operationalinsights/workspaces",
              "gridSettings": {
                "hierarchySettings": {
                  "treeType": 1,
                  "groupBy": [
                    "Identity"
                  ],
                  "expandTopLevel": true
                }
              }
            },
            "conditionalVisibility": {
              "parameterName": "Compare_Collect",
              "comparison": "isEqualTo",
              "value": "True"
            },
            "name": "query - 4"
          },
          {
            "type": 12,
            "content": {
              "version": "NotebookGroup/1.0",
              "groupType": "editable",
              "title": "Transport Rules with specific actions to monitor",
              "items": [
                {
                  "type": 1,
                  "content": {
                    "json": "A  common way used by attackers to exfiltrate data is to set Transport Rules that send all or sensitive messages outside the organization or to a mailbox where they already have full control.\r\n\r\nThis section shows your Transport rules with sentitive actions that can lead to data leaks:\r\n- BlindCopyTo\r\n- SentTo\r\n- CopyTo",
                    "style": "info"
                  },
                  "conditionalVisibility": {
                    "parameterName": "Help",
                    "comparison": "isEqualTo",
                    "value": "Yes"
                  },
                  "name": "TransportRulesHelp"
                },
                {
                  "type": 3,
                  "content": {
                    "version": "KqlItem/1.0",
                    "query": "ExchangeConfiguration(SpecificSectionList=\"TransportRule\",SpecificConfigurationDate=\"{DateOfConfiguration:value}\",SpecificConfigurationEnv={EnvironmentList},Target = \"Online\")\r\n| project CmdletResultValue\r\n| extend Identity = iif( CmdletResultValue.Identity contains \"OrgHierarchyToIgnore\",tostring(CmdletResultValue.Identity.Name),tostring(CmdletResultValue.Identity))\r\n| extend State = tostring(CmdletResultValue.State)\r\n| extend SentTo = tostring(CmdletResultValue.SentToString)\r\n| extend BlindCopyTo = tostring(CmdletResultValue.BlindCopyToString)\r\n| extend CopyTo = tostring(CmdletResultValue.CopyToString)\r\n| extend RedirectMessageTo = tostring(CmdletResultValue.RedirectMessageToString)\r\n| extend SetSCL = tostring(CmdletResultValue.SetSCL)\r\n| extend SenderIpRangesString = tostring(CmdletResultValue.SenderIpRangesString)\r\n| extend MessageTypeMatchesString = tostring(CmdletResultValue.MessageTypeMatchesString)\r\n| extend Mode = tostring(CmdletResultValue.Mode)\r\n| project-away CmdletResultValue\r\n| sort  by Identity asc",
                    "size": 1,
                    "showAnalytics": true,
                    "showExportToExcel": true,
                    "queryType": 0,
                    "resourceType": "microsoft.operationalinsights/workspaces"
                  },
                  "name": "query - 1",
                  "styleSettings": {
                    "showBorder": true
                  }
                }
              ]
            },
            "name": "Transport Rules actions to monitor"
          },
          {
            "type": 1,
            "content": {
              "json": "** Due to lack of informaiton in Powershell, the Transport Rule compare section could display approximate information for Add and Modif. Especially, for the WhenCreated parameter."
            },
            "name": "text - 7"
          },
          {
            "type": 3,
            "content": {
              "version": "KqlItem/1.0",
              "query": "let _EnvList ={EnvironmentList};\r\nlet _TypeEnv = \"Online\";\r\nlet _DateCompare = \"{DateCompare:value}\";\r\nlet _CurrentDate = \"{DateOfConfiguration:value}\";\r\nlet _DateCompareB = todatetime(_DateCompare);\r\nlet _currD = (ExchangeConfiguration(SpecificSectionList=\"TransportRule\",SpecificConfigurationDate=_CurrentDate,SpecificConfigurationEnv=_EnvList,Target = _TypeEnv)\r\n| summarize TimeMax = arg_max(TimeGenerated,*)\r\n| extend TimeMax = tostring(split(TimeMax,\"T\")[0])\r\n| project TimeMax);\r\nlet _CurrentDateB = todatetime(toscalar(_currD));\r\nlet BeforeData =  ExchangeConfiguration(SpecificSectionList=\"TransportRule\",SpecificConfigurationDate=_DateCompareB,SpecificConfigurationEnv=_EnvList,Target = _TypeEnv)\r\n    | extend Identity = tostring(CmdletResultValue.Identity)\r\n\t| extend SentTo = tostring(CmdletResultValue.SentToString)\r\n\t| extend BlindCopyTo = tostring(CmdletResultValue.BlindCopyToString)\r\n\t| extend CopyTo = tostring(CmdletResultValue.CopyToString)\r\n\t| extend RedirectMessageTo = tostring(CmdletResultValue.RedirectMessageToString)\r\n\t| extend Mode = tostring(CmdletResultValue.Mode)\r\n    | extend SetSCL = tostring(CmdletResultValue.SetSCL)\r\n    | extend SenderIpRangesString = tostring(CmdletResultValue.SenderIpRangesString)\r\n    | extend MessageTypeMatchesString = tostring(CmdletResultValue.MessageTypeMatchesString)\r\n    | extend CmdletResultValue.RedirectMessageToString\r\n\t| extend WhenChanged = todatetime(WhenChanged)\r\n    | extend WhenCreated = todatetime(WhenCreated)\r\n;\r\nlet AfterData = \r\n     ExchangeConfiguration(SpecificSectionList=\"TransportRule\",SpecificConfigurationDate=_CurrentDate,SpecificConfigurationEnv=_EnvList,Target = _TypeEnv)\r\n    | extend Identity = tostring(CmdletResultValue.Identity)\r\n\t| extend SentTo = tostring(CmdletResultValue.SentToString)\r\n\t| extend BlindCopyTo = tostring(CmdletResultValue.BlindCopyToString)\r\n\t| extend CopyTo = tostring(CmdletResultValue.CopyToString)\r\n\t| extend RedirectMessageTo = tostring(CmdletResultValue.RedirectMessageToString)\r\n\t| extend Mode = tostring(CmdletResultValue.Mode)\r\n    | extend SetSCL = tostring(CmdletResultValue.SetSCL)\r\n    | extend SenderIpRangesString = tostring(CmdletResultValue.SenderIpRangesString)\r\n    | extend MessageTypeMatchesString = tostring(CmdletResultValue.MessageTypeMatchesString)\r\n\t| extend WhenChanged = todatetime(WhenChanged)\r\n    | extend WhenCreated = todatetime(WhenCreated)\r\n;\r\nlet i=0;\r\nlet allDataRange =\r\n        ESIExchangeOnlineConfig_CL\r\n    | where TimeGenerated between (_DateCompareB .. _CurrentDateB)\r\n    | where ESIEnvironment_s == _EnvList\r\n    | where ExecutionResult_s <> \"EmptyResult\"\r\n    | where Section_s == \"TransportRule\"\r\n    | extend CmdletResultValue = parse_json(rawData_s)\r\n    | project TimeGenerated,CmdletResultValue,WhenChanged = todatetime(WhenChanged_t), WhenCreated=todatetime(WhenCreated_t)\r\n    | extend Identity = tostring(CmdletResultValue.Identity)\r\n\t| sort by Identity,TimeGenerated asc\r\n    | extend SentTo = tostring(CmdletResultValue.SentToString)\r\n\t| extend BlindCopyTo = tostring(CmdletResultValue.BlindCopyToString)\r\n\t| extend CopyTo = tostring(CmdletResultValue.CopyToString)\r\n\t| extend RedirectMessageTo = tostring(CmdletResultValue.RedirectMessageToString)\r\n\t| extend Mode = tostring(CmdletResultValue.Mode)\r\n    | extend CmdletResultValue.RedirectMessageToString\r\n    | extend SetSCL = tostring(CmdletResultValue.SetSCL)\r\n    | extend SenderIpRangesString = tostring(CmdletResultValue.SenderIpRangesString)\r\n    | extend MessageTypeMatchesString = tostring(CmdletResultValue.MessageTypeMatchesString)\r\n    | extend WhenChanged = todatetime(bin(WhenChanged,1m))\r\n    | extend aa=prev(WhenCreated)\r\n    | extend WhenCreated = iff( Identity == prev(Identity) and WhenChanged != prev(WhenChanged),aa ,WhenChanged)\r\n    | extend WhenCreated =bin(WhenCreated,1m)\r\n    ;\r\nlet DiffAddDataP1 = allDataRange\r\n  | join kind = rightanti  (AfterData | where WhenCreated >=_DateCompareB) on WhenCreated\r\n;\r\nlet DiffAddDataP2 = allDataRange\r\n    | join kind = inner   (allDataRange ) on WhenCreated\r\n    | where WhenCreated >=_DateCompareB\r\n    | where bin(WhenCreated,5m)==bin(WhenChanged,5m)\r\n    | distinct  Identity,SentTo,BlindCopyTo,CopyTo,RedirectMessageTo,Mode,SetSCL,SenderIpRangesString,MessageTypeMatchesString,WhenChanged,WhenCreated\r\n ;\r\nlet DiffAddData1 = union DiffAddDataP1,DiffAddDataP2\r\n| extend Actiontype =\"Add\";\r\nlet DiffAddData2 = union DiffAddDataP1,DiffAddDataP2\r\n| extend Actiontype =\"Add\"\r\n| distinct  Identity;\r\nlet DiffAddData = DiffAddData1\r\n| join DiffAddData2 on Identity\r\n;\r\nlet DiffRemoveData = allDataRange\r\n    | join kind = leftanti AfterData on Identity\r\n    | extend Actiontype =\"Remove\"\r\n    | distinct  Actiontype ,Identity,SentTo,BlindCopyTo,CopyTo,RedirectMessageTo,SetSCL,SenderIpRangesString,MessageTypeMatchesString,Mode,WhenChanged,WhenCreated\r\n    | project  WhenChanged=_CurrentDateB,Actiontype,Identity,SentTo,BlindCopyTo,CopyTo,RedirectMessageTo,SetSCL,SenderIpRangesString,MessageTypeMatchesString,Mode,WhenCreated\r\n    ;\r\nlet DiffModifData = union AfterData,allDataRange\r\n| sort by Identity,WhenChanged asc\r\n| project WhenChanged,Identity,SentTo,BlindCopyTo,CopyTo,RedirectMessageTo, SetSCL, SenderIpRangesString,MessageTypeMatchesString,Mode,WhenCreated\r\n| extend Identity = iff( Identity == prev(Identity) and Identity != prev(Identity) and prev(Identity) !=\"\" , strcat(\"📍 \", Identity, \" (\",prev(Identity),\"->\", Identity,\" )\"),Identity)\r\n| extend SentTo = iff( Identity == prev(Identity) and SentTo != prev(SentTo) and prev(SentTo) !=\"\" , strcat(\"📍 \", SentTo, \" (\",prev(SentTo),\"->\", SentTo,\" )\"),SentTo)\r\n| extend BlindCopyTo = iff( Identity == prev(Identity) and BlindCopyTo != prev(BlindCopyTo) and prev(BlindCopyTo) !=\"\" , strcat(\"📍 \", BlindCopyTo, \" (\",prev(BlindCopyTo),\"->\", BlindCopyTo,\" )\"),BlindCopyTo)\r\n| extend CopyTo = iff( Identity == prev(Identity) and CopyTo != prev(CopyTo) and prev(CopyTo) !=\"\" , strcat(\"📍 \", CopyTo, \" (\",prev(CopyTo),\"->\", CopyTo,\" )\"),CopyTo)\r\n| extend SetSCL = iff( Identity == prev(Identity)and SetSCL != prev(SetSCL) and prev(SetSCL) !=\"\" , strcat(\"📍 \", SetSCL, \" (\",prev(SetSCL),\"->\", SetSCL,\" )\"),SetSCL)\r\n| extend SenderIpRangesString = iff( Identity == prev(Identity)and SenderIpRangesString != prev(SenderIpRangesString) and prev(SenderIpRangesString) !=\"\" , strcat(\"📍 \", SenderIpRangesString, \" (\",prev(SenderIpRangesString),\"->\", SenderIpRangesString,\" )\"),SenderIpRangesString)\r\n| extend MessageTypeMatchesString = iff( Identity == prev(Identity)and MessageTypeMatchesString != prev(MessageTypeMatchesString) and prev(MessageTypeMatchesString) !=\"\" , strcat(\"📍 \", MessageTypeMatchesString, \" (\",prev(MessageTypeMatchesString),\"->\", MessageTypeMatchesString,\" )\"),MessageTypeMatchesString)\r\n| extend Mode = iff( Identity == prev(Identity)and Mode != prev(Mode) and prev(Mode) !=\"\" , strcat(\"📍 \", Mode, \" (\",prev(Mode),\"->\", Mode,\" )\"),Mode)\r\n| extend ActiontypeR =iff((Identity contains \"📍\" or SentTo contains \"📍\" or BlindCopyTo contains \"📍\" or CopyTo contains \"📍\" or SetSCL contains \"📍\" or SenderIpRangesString contains \"📍\" or MessageTypeMatchesString contains \"📍\" or Mode contains \"📍\" ), i=i + 1, i)\r\n| extend Actiontype =iff(ActiontypeR > 0, \"Modif\", \"NO\")\r\n| where ActiontypeR == 1\r\n| project WhenChanged,Actiontype,Identity,SentTo,BlindCopyTo,CopyTo,RedirectMessageTo,SetSCL,SenderIpRangesString,MessageTypeMatchesString,Mode,WhenCreated\r\n;\r\nunion DiffAddData, DiffRemoveData, DiffModifData\r\n| extend WhenChanged = iff (Actiontype == \"Modif\", WhenChanged, iff(Actiontype == \"Add\",WhenCreated, WhenChanged))\r\n| extend Actiontype = case(Actiontype == \"Add\", strcat(\"➕ \", Actiontype), Actiontype == \"Remove\", strcat(\"➖ \", Actiontype), Actiontype == \"Modif\", strcat(\"📍 \", Actiontype), \"N/A\")\r\n| sort by WhenChanged desc \r\n| project\r\n    WhenChanged,\r\n    Actiontype,\r\n    Identity,\r\n    SentTo,\r\n    BlindCopyTo,\r\n    CopyTo,\r\n    RedirectMessageTo,\r\n    SetSCL,\r\n    SenderIpRangesString,\r\n    MessageTypeMatchesString,\r\n    Mode,\r\n    WhenCreated",
              "size": 3,
              "showAnalytics": true,
              "title": "Display changes ( Add, Remove, modifications of parameters )",
              "showExportToExcel": true,
              "queryType": 0,
              "resourceType": "microsoft.operationalinsights/workspaces",
              "gridSettings": {
                "hierarchySettings": {
                  "treeType": 1,
                  "groupBy": [
                    "Identity"
                  ],
                  "expandTopLevel": true
                }
              }
            },
            "conditionalVisibility": {
              "parameterName": "Compare_Collect",
              "comparison": "isEqualTo",
              "value": "True"
            },
            "name": "query - 5"
          },
          {
            "type": 12,
            "content": {
              "version": "NotebookGroup/1.0",
              "groupType": "editable",
              "title": "Outbound Policy :  Autoforward configuration",
              "items": [
                {
                  "type": 1,
                  "content": {
                    "json": "If **AutoForwardEnabled** is enabled, then automatic transfer are allowed.\r\nFor example: users in Outlook will be able set automatic transfer of all their emails to external addresses.\r\nThere are several methods to authorized automatic forward. \r\nPlease review this article : https://learn.microsoft.com/microsoft-365/security/office-365-security/outbound-spam-policies-external-email-forwarding?view=o365-worldwide\r\n**In summary :**\r\n\r\n**Scenario 1 :**\r\n\r\nYou configure remote domain settings to allow automatic forwarding.\r\nAutomatic forwarding in the outbound spam filter policy is set to Off.\r\n*Result :* \r\nAutomatically forwarded messages to recipients in the affected domains are blocked.\r\n\r\n**Scenario 2 :**\r\n\r\nYou configure remote domain settings to allow automatic forwarding.\r\nAutomatic forwarding in the outbound spam filter policy is set to Automatic - System-controlled.\r\n\r\n*Result :* \r\n\r\nAutomatically forwarded messages to recipients in the affected domains are blocked.\r\nAs described earlier, Automatic - System-controlled used to mean On, but the setting has changed over time to mean Off in all organizations.\r\n\r\nFor absolute clarity, you should configure your outbound spam filter policy to On or Off.\r\n\r\n**Scenario 3 :**\r\n\r\nAutomatic forwarding in the outbound spam filter policy is set to On\r\nYou use mail flow rules or remote domains to block automatically forwarded email\r\n\r\n*Result : *\r\n\r\nAutomatically forwarded messages to affected recipients are blocked by mail flow rules or remote domains.\r\n****\r\nAlso, when setting AutoForwardEnabled to a specific domain, it is strongly recommended enable TLS encryption.",
                    "style": "info"
                  },
                  "conditionalVisibility": {
                    "parameterName": "Help",
                    "comparison": "isEqualTo",
                    "value": "Yes"
                  },
                  "name": "AutoForwardHelp"
                },
                {
                  "type": 3,
                  "content": {
                    "version": "KqlItem/1.0",
                    "query": "let HOSFR = ExchangeConfiguration(SpecificSectionList=\"HostedOutboundSpamFilterRule\", SpecificConfigurationDate=\"{DateOfConfiguration:value}\",SpecificConfigurationEnv={EnvironmentList},Target = \"Online\")\r\n| extend HostedOutboundSpamFilterPolicy = tostring(CmdletResultValue.HostedOutboundSpamFilterPolicy)\r\n| project Identity,HostedOutboundSpamFilterPolicy;\r\nExchangeConfiguration(SpecificSectionList=\"HostedOutboundSpamFilterPolicy\",SpecificConfigurationDate=\"{DateOfConfiguration:value}\",SpecificConfigurationEnv={EnvironmentList},Target = \"Online\")\r\n| extend Identity =  tostring(CmdletResultValue.Identity)\r\n| join kind = fullouter  HOSFR on $left.Identity == $right.HostedOutboundSpamFilterPolicy\r\n| extend OutboundSpamFilterRule =  tostring(Identity1)\r\n| extend  IsDefault=  tostring(CmdletResultValue.IsDefault)\r\n| extend  Enabled=  tostring(CmdletResultValue.Enabled)\r\n| extend  AutoForwardingMode= iff (CmdletResultValue.AutoForwardingMode == \"On\" , strcat (\"❌ \", tostring(CmdletResultValue.AutoForwardingMode)), tostring(CmdletResultValue.AutoForwardingMode))\r\n| extend  RecommendedPolicyType=  tostring(CmdletResultValue.RecommendedPolicyType)\r\n| extend  RecipientLimitExternalPerHour =  tostring(CmdletResultValue.RecipientLimitExternalPerHour)\r\n| extend  RecipientLimitInternalPerHour =  tostring(CmdletResultValue.RecipientLimitInternalPerHour)\r\n| extend  RecipientLimitPerDay=  tostring(CmdletResultValue.RecipientLimitPerDay)\r\n| extend  ActionWhenThresholdReached =  tostring(CmdletResultValue.ActionWhenThresholdReached)\r\n| extend  BccSuspiciousOutboundAdditionalRecipients=  tostring(CmdletResultValue.BccSuspiciousOutboundAdditionalRecipients)\r\n| extend  BccSuspiciousOutboundMail =  tostring(CmdletResultValue.BccSuspiciousOutboundMail)\r\n| extend  NotifyOutboundSpam=  tostring(CmdletResultValue.NotifyOutboundSpam)\r\n| extend  NotifyOutboundSpamRecipient =  tostring(CmdletResultValue.NotifyOutboundSpamRecipient)\r\n| project Identity,IsDefault,Enabled,AutoForwardingMode,OutboundSpamFilterRule,BccSuspiciousOutboundAdditionalRecipients,BccSuspiciousOutboundMail,NotifyOutboundSpam,NotifyOutboundSpamRecipient,WhenChanged,WhenCreated\r\n| sort by Identity asc ",
                    "size": 1,
                    "showAnalytics": true,
                    "showExportToExcel": true,
                    "queryType": 0,
                    "resourceType": "microsoft.operationalinsights/workspaces",
                    "gridSettings": {
                      "rowLimit": 10000,
                      "filter": true
                    }
                  },
                  "name": "query - 1",
                  "styleSettings": {
                    "showBorder": true
                  }
                }
              ]
            },
            "name": "OutboundPol - Copy"
          },
          {
            "type": 3,
            "content": {
              "version": "KqlItem/1.0",
              "query": "let _EnvList ={EnvironmentList};\r\nlet _TypeEnv = \"Online\";\r\nlet _DateCompare = \"{DateCompare:value}\";\r\nlet _CurrentDate = \"{DateOfConfiguration:value}\";\r\nlet _DateCompareB = todatetime(_DateCompare);\r\nlet _currD = (ExchangeConfiguration(SpecificSectionList=\"HostedOutboundSpamFilterPolicy\",SpecificConfigurationDate=_CurrentDate,SpecificConfigurationEnv=_EnvList,Target = _TypeEnv)\r\n| summarize TimeMax = arg_max(TimeGenerated,*)\r\n| extend TimeMax = tostring(split(TimeMax,\"T\")[0])\r\n| project TimeMax);\r\nlet _CurrentDateB = todatetime(toscalar(_currD));\r\nlet HOSFR = ExchangeConfiguration(SpecificSectionList=\"HostedOutboundSpamFilterRule\", SpecificConfigurationDate=\"{DateOfConfiguration:value}\",SpecificConfigurationEnv={EnvironmentList},Target = \"Online\")\r\n| extend HostedOutboundSpamFilterPolicy = tostring(CmdletResultValue.HostedOutboundSpamFilterPolicy)\r\n| project Identity,HostedOutboundSpamFilterPolicy;\r\nlet BeforeData =  ExchangeConfiguration(SpecificSectionList=\"HostedOutboundSpamFilterPolicy\", SpecificConfigurationDate=_DateCompareB, SpecificConfigurationEnv=_EnvList, Target = _TypeEnv)\r\n    | extend Identity =  tostring(Identity)\r\n    | join kind = fullouter HOSFR on $left.Identity == $right.HostedOutboundSpamFilterPolicy\r\n    | extend OutboundSpamFilterRule =  tostring(Identity1)\r\n    | extend IsDefault=  tostring(CmdletResultValue.IsDefault)\r\n    | extend Enabled=  tostring(CmdletResultValue.Enabled)\r\n    | extend AutoForwardingMode=  tostring(CmdletResultValue.AutoForwardingMode)\r\n    | extend RecommendedPolicyType=  tostring(CmdletResultValue.RecommendedPolicyType)\r\n    | extend RecipientLimitExternalPerHour =  tostring(CmdletResultValue.RecipientLimitExternalPerHour)\r\n    | extend RecipientLimitInternalPerHour =  tostring(CmdletResultValue.RecipientLimitInternalPerHour)\r\n    | extend RecipientLimitPerDay=  tostring(CmdletResultValue.RecipientLimitPerDay)\r\n    | extend ActionWhenThresholdReached =  tostring(CmdletResultValue.ActionWhenThresholdReached)\r\n    | extend BccSuspiciousOutboundAdditionalRecipients=  tostring(CmdletResultValue.BccSuspiciousOutboundAdditionalRecipients)\r\n    | extend BccSuspiciousOutboundMail =  tostring(CmdletResultValue.BccSuspiciousOutboundMail)\r\n    | extend NotifyOutboundSpam=  tostring(CmdletResultValue.NotifyOutboundSpam)\r\n    | extend NotifyOutboundSpamRecipient =  tostring(CmdletResultValue.NotifyOutboundSpamRecipient)\r\n    | extend WhenChanged = todatetime(WhenChanged)\r\n    | extend WhenCreated = todatetime(WhenCreated)\r\n;\r\nlet AfterData = \r\n    ExchangeConfiguration(SpecificSectionList=\"HostedOutboundSpamFilterPolicy\", SpecificConfigurationDate=_CurrentDate, SpecificConfigurationEnv=_EnvList, Target = _TypeEnv)\r\n    | extend Identity =  tostring(Identity)\r\n    | join kind = fullouter HOSFR on $left.Identity == $right.HostedOutboundSpamFilterPolicy\r\n    | extend OutboundSpamFilterRule =  tostring(Identity1)\r\n    | extend IsDefault=  tostring(CmdletResultValue.IsDefault)\r\n    | extend Enabled=  tostring(CmdletResultValue.Enabled)\r\n    | extend AutoForwardingMode=  tostring(CmdletResultValue.AutoForwardingMode)\r\n    | extend RecommendedPolicyType=  tostring(CmdletResultValue.RecommendedPolicyType)\r\n    | extend RecipientLimitExternalPerHour =  tostring(CmdletResultValue.RecipientLimitExternalPerHour)\r\n    | extend RecipientLimitInternalPerHour =  tostring(CmdletResultValue.RecipientLimitInternalPerHour)\r\n    | extend RecipientLimitPerDay=  tostring(CmdletResultValue.RecipientLimitPerDay)\r\n    | extend ActionWhenThresholdReached =  tostring(CmdletResultValue.ActionWhenThresholdReached)\r\n    | extend BccSuspiciousOutboundAdditionalRecipients=  tostring(CmdletResultValue.BccSuspiciousOutboundAdditionalRecipients)\r\n    | extend BccSuspiciousOutboundMail =  tostring(CmdletResultValue.BccSuspiciousOutboundMail)\r\n    | extend NotifyOutboundSpam=  tostring(CmdletResultValue.NotifyOutboundSpam)\r\n    | extend NotifyOutboundSpamRecipient =  tostring(CmdletResultValue.NotifyOutboundSpamRecipient)\r\n    | extend WhenChanged = todatetime(WhenChanged)\r\n    | extend WhenCreated = todatetime(WhenCreated)\r\n;\r\nlet i=0;\r\nlet allDataRangeOSFR = ESIExchangeOnlineConfig_CL\r\n    | where TimeGenerated between (_DateCompareB .. _CurrentDateB)\r\n    | where ESIEnvironment_s == _EnvList\r\n    | where ExecutionResult_s <> \"EmptyResult\"\r\n    | where Section_s == \"HostedOutboundSpamFilterRule\"\r\n    | extend CmdletResultValue = parse_json(rawData_s)\r\n    | extend Identity =  tostring(CmdletResultValue.Identity)\r\n    | extend HostedOutboundSpamFilterPolicy = tostring(CmdletResultValue.HostedOutboundSpamFilterPolicy)\r\n    | project Identity, HostedOutboundSpamFilterPolicy;\r\nlet allDataRange = \r\n    ESIExchangeOnlineConfig_CL\r\n    | where TimeGenerated between (_DateCompareB .. _CurrentDateB)\r\n    | where ESIEnvironment_s == _EnvList\r\n    | where ExecutionResult_s <> \"EmptyResult\"\r\n    | where Section_s == \"HostedOutboundSpamFilterPolicy\"\r\n    | extend CmdletResultValue = parse_json(rawData_s)\r\n    | extend Identity =  tostring(CmdletResultValue.Identity)\r\n    | project\r\n        TimeGenerated,\r\n        Identity,\r\n        CmdletResultValue,\r\n        WhenChanged = todatetime(bin(WhenChanged_t,1m)),\r\n        WhenCreated=todatetime(bin(WhenCreated_t,1m))\r\n    | join kind=fullouter allDataRangeOSFR on $left.Identity == $right.HostedOutboundSpamFilterPolicy\r\n    | extend OutboundSpamFilterRule =  tostring(Identity1)\r\n    | extend IsDefault=  tostring(CmdletResultValue.IsDefault)\r\n    | extend Enabled=  tostring(CmdletResultValue.Enabled)\r\n    | extend AutoForwardingMode=  tostring(CmdletResultValue.AutoForwardingMode)\r\n    | extend RecommendedPolicyType=  tostring(CmdletResultValue.RecommendedPolicyType)\r\n    | extend RecipientLimitExternalPerHour =  tostring(CmdletResultValue.RecipientLimitExternalPerHour)\r\n    | extend RecipientLimitInternalPerHour =  tostring(CmdletResultValue.RecipientLimitInternalPerHour)\r\n    | extend RecipientLimitPerDay=  tostring(CmdletResultValue.RecipientLimitPerDay)\r\n    | extend ActionWhenThresholdReached =  tostring(CmdletResultValue.ActionWhenThresholdReached)\r\n    | extend BccSuspiciousOutboundAdditionalRecipients=  tostring(CmdletResultValue.BccSuspiciousOutboundAdditionalRecipients)\r\n    | extend BccSuspiciousOutboundMail =  tostring(CmdletResultValue.BccSuspiciousOutboundMail)\r\n    | extend NotifyOutboundSpam=  tostring(CmdletResultValue.NotifyOutboundSpam)\r\n    | extend NotifyOutboundSpamRecipient =  tostring(CmdletResultValue.NotifyOutboundSpamRecipient)\r\n    | distinct\r\n        WhenChanged,\r\n        Identity,\r\n        IsDefault,\r\n        Enabled,\r\n        AutoForwardingMode,\r\n        OutboundSpamFilterRule,\r\n        RecommendedPolicyType,\r\n        RecipientLimitExternalPerHour,\r\n        RecipientLimitInternalPerHour,\r\n        ActionWhenThresholdReached,\r\n        RecipientLimitPerDay,\r\n        BccSuspiciousOutboundAdditionalRecipients,\r\n        BccSuspiciousOutboundMail,\r\n        NotifyOutboundSpam,\r\n        NotifyOutboundSpamRecipient,\r\n        WhenCreated \r\n;\r\nlet DiffAddDataP1 = allDataRange\r\n    | join kind = rightanti  (AfterData\r\n        | where WhenCreated >= _DateCompareB)\r\n        on WhenCreated\r\n;\r\nlet DiffAddDataP2 = allDataRange\r\n    | join kind = innerunique   (allDataRange) on WhenCreated\r\n    | where WhenCreated >= _DateCompareB\r\n    | where bin(WhenCreated, 5m) == bin(WhenChanged, 5m)\r\n    | distinct\r\n        Identity,\r\n        IsDefault,\r\n        Enabled,\r\n        AutoForwardingMode,\r\n        OutboundSpamFilterRule,\r\n        RecommendedPolicyType,\r\n        RecipientLimitExternalPerHour,\r\n        RecipientLimitInternalPerHour,\r\n        ActionWhenThresholdReached,\r\n        RecipientLimitPerDay,\r\n        BccSuspiciousOutboundAdditionalRecipients,\r\n        BccSuspiciousOutboundMail,\r\n        NotifyOutboundSpam,\r\n        NotifyOutboundSpamRecipient,\r\n        WhenCreated \r\n;\r\nlet DiffAddData = union DiffAddDataP1, DiffAddDataP2\r\n    | extend Actiontype =\"Add\";\r\nlet DiffRemoveData = allDataRange\r\n    | join kind = leftanti AfterData on Identity\r\n    | extend Actiontype =\"Remove\"\r\n    | distinct\r\n        Actiontype,\r\n        Identity,\r\n        IsDefault,\r\n        Enabled,\r\n        AutoForwardingMode,\r\n        OutboundSpamFilterRule,\r\n        RecommendedPolicyType,\r\n        RecipientLimitExternalPerHour,\r\n        RecipientLimitInternalPerHour,\r\n        ActionWhenThresholdReached,\r\n        RecipientLimitPerDay,\r\n        BccSuspiciousOutboundAdditionalRecipients,\r\n        BccSuspiciousOutboundMail,\r\n        NotifyOutboundSpam,\r\n        NotifyOutboundSpamRecipient,\r\n        WhenCreated \r\n    | project\r\n        WhenChanged=_CurrentDateB,\r\n        Actiontype,\r\n        Identity,\r\n        IsDefault,\r\n        Enabled,\r\n        AutoForwardingMode,\r\n        OutboundSpamFilterRule,\r\n        RecommendedPolicyType,\r\n        RecipientLimitExternalPerHour,\r\n        RecipientLimitInternalPerHour,\r\n        ActionWhenThresholdReached,\r\n        RecipientLimitPerDay,\r\n        BccSuspiciousOutboundAdditionalRecipients,\r\n        BccSuspiciousOutboundMail,\r\n        NotifyOutboundSpam,\r\n        NotifyOutboundSpamRecipient,\r\n        WhenCreated\r\n;\r\nlet DiffModifData = union AfterData, allDataRange\r\n    | sort by Identity, WhenChanged asc\r\n    | project\r\n        WhenChanged,\r\n        Identity,\r\n        IsDefault,\r\n        Enabled,\r\n        AutoForwardingMode,\r\n        OutboundSpamFilterRule,\r\n        RecommendedPolicyType,\r\n        RecipientLimitExternalPerHour,\r\n        RecipientLimitInternalPerHour,\r\n        ActionWhenThresholdReached,\r\n        RecipientLimitPerDay,\r\n        BccSuspiciousOutboundAdditionalRecipients,\r\n        BccSuspiciousOutboundMail,\r\n        NotifyOutboundSpam,\r\n        NotifyOutboundSpamRecipient,\r\n        WhenCreated \r\n    | extend Identity = iff(Identity == prev(Identity) and Identity != prev(Identity) and prev(Identity) != \"\", strcat(\"📍 \", Identity, \" (\", prev(Identity), \"->\", Identity, \" )\"), Identity)\r\n    | extend IsDefault = iff(Identity == prev(Identity) and IsDefault != prev(IsDefault) and prev(IsDefault) != \"\", strcat(\"📍 \", IsDefault, \" (\", prev(IsDefault), \"->\", IsDefault, \" )\"), IsDefault)\r\n    | extend Enabled = iff(Identity == prev(Identity) and Enabled != prev(Enabled) and prev(Enabled) != \"\", strcat(\"📍 \", Enabled, \" (\", prev(Enabled), \"->\", Enabled, \" )\"), Enabled)\r\n    | extend AutoForwardingMode = iff(Identity == prev(Identity) and AutoForwardingMode != prev(AutoForwardingMode) and prev(AutoForwardingMode) != \"\", strcat(\"📍 \", AutoForwardingMode, \" (\", prev(AutoForwardingMode), \"->\", AutoForwardingMode, \" )\"), AutoForwardingMode)\r\n    | extend OutboundSpamFilterRule = iff(Identity == prev(Identity) and OutboundSpamFilterRule != prev(OutboundSpamFilterRule) and prev(OutboundSpamFilterRule) != \"\", strcat(\"📍 \", OutboundSpamFilterRule, \" (\", prev(OutboundSpamFilterRule), \"->\", OutboundSpamFilterRule, \" )\"), OutboundSpamFilterRule)\r\n    | extend RecommendedPolicyType = iff(Identity == prev(Identity) and RecommendedPolicyType != prev(RecommendedPolicyType) and prev(RecommendedPolicyType) != \"\", strcat(\"📍 \", RecommendedPolicyType, \" (\", prev(RecommendedPolicyType), \"->\", RecommendedPolicyType, \" )\"), RecommendedPolicyType)\r\n    | extend RecipientLimitExternalPerHour = iff(Identity == prev(Identity) and RecipientLimitExternalPerHour != prev(RecipientLimitExternalPerHour) and prev(RecipientLimitExternalPerHour) != \"\", strcat(\"📍 \", RecipientLimitExternalPerHour, \" (\", prev(RecipientLimitExternalPerHour), \"->\", RecipientLimitExternalPerHour, \" )\"), RecipientLimitExternalPerHour)\r\n    | extend RecipientLimitInternalPerHour = iff(Identity == prev(Identity) and RecipientLimitInternalPerHour != prev(RecipientLimitInternalPerHour) and prev(RecipientLimitInternalPerHour) != \"\", strcat(\"📍 \", RecipientLimitInternalPerHour, \" (\", prev(RecipientLimitInternalPerHour), \"->\", RecipientLimitInternalPerHour, \" )\"), RecipientLimitInternalPerHour)\r\n    | extend ActionWhenThresholdReached = iff(Identity == prev(Identity) and ActionWhenThresholdReached != prev(ActionWhenThresholdReached) and prev(ActionWhenThresholdReached) != \"\", strcat(\"📍 \", ActionWhenThresholdReached, \" (\", prev(ActionWhenThresholdReached), \"->\", ActionWhenThresholdReached, \" )\"), ActionWhenThresholdReached)\r\n    | extend RecipientLimitPerDay = iff(Identity == prev(Identity) and RecipientLimitPerDay != prev(RecipientLimitPerDay) and prev(RecipientLimitPerDay) != \"\", strcat(\"📍 \", RecipientLimitPerDay, \" (\", prev(RecipientLimitPerDay), \"->\", RecipientLimitPerDay, \" )\"), RecipientLimitPerDay)\r\n    | extend BccSuspiciousOutboundAdditionalRecipients = iff(Identity == prev(Identity) and BccSuspiciousOutboundAdditionalRecipients != prev(BccSuspiciousOutboundAdditionalRecipients) and prev(BccSuspiciousOutboundAdditionalRecipients) != \"\", strcat(\"📍 \", BccSuspiciousOutboundAdditionalRecipients, \" (\", prev(BccSuspiciousOutboundAdditionalRecipients), \"->\", BccSuspiciousOutboundAdditionalRecipients, \" )\"), BccSuspiciousOutboundAdditionalRecipients)\r\n    | extend BccSuspiciousOutboundMail = iff(Identity == prev(Identity) and BccSuspiciousOutboundMail != prev(BccSuspiciousOutboundMail) and prev(BccSuspiciousOutboundMail) != \"\", strcat(\"📍 \", BccSuspiciousOutboundMail, \" (\", prev(BccSuspiciousOutboundMail), \"->\", BccSuspiciousOutboundMail, \" )\"), BccSuspiciousOutboundMail)\r\n    | extend NotifyOutboundSpam = iff(Identity == prev(Identity) and NotifyOutboundSpam != prev(NotifyOutboundSpam) and prev(NotifyOutboundSpam) != \"\", strcat(\"📍 \", NotifyOutboundSpam, \" (\", prev(NotifyOutboundSpam), \"->\", NotifyOutboundSpam, \" )\"), NotifyOutboundSpam)\r\n    | extend NotifyOutboundSpamRecipient = iff(Identity == prev(Identity) and NotifyOutboundSpamRecipient != prev(NotifyOutboundSpamRecipient) and prev(NotifyOutboundSpamRecipient) != \"\", strcat(\"📍 \", NotifyOutboundSpamRecipient, \" (\", prev(NotifyOutboundSpamRecipient), \"->\", NotifyOutboundSpamRecipient, \" )\"), NotifyOutboundSpamRecipient)\r\n    | extend ActiontypeR =iff((Identity contains \"📍\" or IsDefault contains \"📍\" or Enabled contains \"📍\" or OutboundSpamFilterRule contains \"📍\" or AutoForwardingMode contains \"📍\" or BccSuspiciousOutboundAdditionalRecipients contains \"📍\" or BccSuspiciousOutboundMail contains \"📍\" or NotifyOutboundSpam contains \"📍\" or NotifyOutboundSpamRecipient contains \"📍\"), i=i + 1, i)\r\n    | extend Actiontype =iff(ActiontypeR > 0, \"Modif\", \"NO\")\r\n    | where ActiontypeR == 1\r\n    | distinct\r\n        WhenChanged,\r\n        Actiontype,\r\n        Identity,\r\n        IsDefault,\r\n        Enabled,\r\n        AutoForwardingMode,\r\n        OutboundSpamFilterRule,\r\n        RecommendedPolicyType,\r\n        RecipientLimitExternalPerHour,\r\n        RecipientLimitInternalPerHour,\r\n        ActionWhenThresholdReached,\r\n        RecipientLimitPerDay,\r\n        BccSuspiciousOutboundAdditionalRecipients,\r\n        BccSuspiciousOutboundMail,\r\n        NotifyOutboundSpam,\r\n        NotifyOutboundSpamRecipient,\r\n        WhenCreated \r\n;\r\nunion DiffAddData, DiffRemoveData, DiffModifData\r\n| extend WhenChanged = iff (Actiontype == \"Modif\", WhenChanged, iff(Actiontype == \"Add\", WhenCreated, WhenChanged))\r\n| extend Actiontype = case(Actiontype == \"Add\", strcat(\"➕ \", Actiontype), Actiontype == \"Remove\", strcat(\"➖ \", Actiontype), Actiontype == \"Modif\", strcat(\"📍 \", Actiontype), \"N/A\")\r\n| sort by WhenChanged desc \r\n| project\r\n    WhenChanged,\r\n    Actiontype,\r\n    Identity,\r\n    IsDefault,\r\n    Enabled,\r\n    AutoForwardingMode,\r\n    OutboundSpamFilterRule,\r\n    RecommendedPolicyType,\r\n    RecipientLimitExternalPerHour,\r\n    RecipientLimitInternalPerHour,\r\n    ActionWhenThresholdReached,\r\n    RecipientLimitPerDay,\r\n    BccSuspiciousOutboundAdditionalRecipients,\r\n    BccSuspiciousOutboundMail,\r\n    NotifyOutboundSpam,\r\n    NotifyOutboundSpamRecipient,\r\n    WhenCreated ",
              "size": 3,
              "showAnalytics": true,
              "title": "Display changes ( Add, Remove, modifications of parameters )",
              "showExportToExcel": true,
              "queryType": 0,
              "resourceType": "microsoft.operationalinsights/workspaces",
              "gridSettings": {
                "hierarchySettings": {
                  "treeType": 1,
                  "groupBy": [
                    "Identity"
                  ],
                  "expandTopLevel": true
                }
              }
            },
            "conditionalVisibility": {
              "parameterName": "Compare_Collect",
              "comparison": "isEqualTo",
              "value": "True"
            },
            "name": "query - 7 - Copy"
          },
          {
            "type": 12,
            "content": {
              "version": "NotebookGroup/1.0",
              "groupType": "editable",
              "title": "Remote Domain Autofoward Configuration - * should not allow AutoForwardEnabled",
              "items": [
                {
                  "type": 1,
                  "content": {
                    "json": "If **AutoForwardEnabled** is set to True for an SMTP domain and the Outbound Policy is set to On then users in Outlook are allowed to set automatic transfer of all their emails to addresses in this domain.\r\n\r\nWhen the Default Remote domain is set to * and has the AutoForwardEnabled set True, any user can configure an Outlook rule to automatically forward all emails to any SMTP domain domains outside the organization. This is a high risk configuration as it might allow accounts to leak information. \r\n\r\nAlso, when setting AutoForwardEnabled to a specific domain, it is strongly recommended enable TLS encryption.",
                    "style": "info"
                  },
                  "conditionalVisibility": {
                    "parameterName": "Help",
                    "comparison": "isEqualTo",
                    "value": "Yes"
                  },
                  "name": "AutoForwardHelp"
                },
                {
                  "type": 3,
                  "content": {
                    "version": "KqlItem/1.0",
                    "query": "ExchangeConfiguration(SpecificSectionList=\"RemoteDomain\",SpecificConfigurationDate=\"{DateOfConfiguration:value}\",SpecificConfigurationEnv={EnvironmentList},Target = \"Online\")\r\n| project CmdletResultValue\r\n| extend Name =  tostring(CmdletResultValue.Name)\r\n| extend Address =  tostring(CmdletResultValue.DomainName)\r\n| extend AutoForwardEnabled =  iff (CmdletResultValue.AutoForwardEnabled== \"true\" and CmdletResultValue.DomainName == \"*\", strcat (\"❌ \",tostring(CmdletResultValue.AutoForwardEnabled)),iff(CmdletResultValue.AutoForwardEnabled== \"true\" and CmdletResultValue.DomainName != \"*\", strcat (\"⚠️ \",tostring(CmdletResultValue.AutoForwardEnabled)),strcat (\"✅ \",tostring(CmdletResultValue.AutoForwardEnabled))))\r\n| project-away CmdletResultValue\r\n| sort  by Address asc ",
                    "size": 1,
                    "showAnalytics": true,
                    "showExportToExcel": true,
                    "queryType": 0,
                    "resourceType": "microsoft.operationalinsights/workspaces",
                    "gridSettings": {
                      "rowLimit": 10000,
                      "filter": true
                    }
                  },
                  "name": "query - 1",
                  "styleSettings": {
                    "showBorder": true
                  }
                }
              ]
            },
            "name": "ForwardGroup"
          },
          {
            "type": 3,
            "content": {
              "version": "KqlItem/1.0",
              "query": "let _EnvList ={EnvironmentList};\r\nlet _TypeEnv = \"Online\";\r\nlet _DateCompare = \"{DateCompare:value}\";\r\nlet _CurrentDate = \"{DateOfConfiguration:value}\";\r\nlet _DateCompareB = todatetime(_DateCompare);\r\nlet _currD = (ExchangeConfiguration(SpecificSectionList=\"RemoteDomain\",SpecificConfigurationDate=_CurrentDate,SpecificConfigurationEnv=_EnvList,Target = _TypeEnv)\r\n| summarize TimeMax = arg_max(TimeGenerated,*)\r\n| extend TimeMax = tostring(split(TimeMax,\"T\")[0])\r\n| project TimeMax);\r\nlet _CurrentDateB = todatetime(toscalar(_currD));\r\nlet BeforeData =  ExchangeConfiguration(SpecificSectionList=\"RemoteDomain\",SpecificConfigurationDate=_DateCompareB,SpecificConfigurationEnv=_EnvList,Target = _TypeEnv)\r\n    | extend Identity = tostring(CmdletResultValue.Name)\r\n\t| extend DomainName  = tostring(CmdletResultValue.DomainName)\r\n\t| extend AutoForwardEnabled = tostring(CmdletResultValue.AutoForwardEnabled)\r\n\t| extend WhenChanged = todatetime(WhenChanged)\r\n    | extend WhenCreated = todatetime(WhenCreated)\r\n;\r\nlet AfterData = \r\n     ExchangeConfiguration(SpecificSectionList=\"RemoteDomain\",SpecificConfigurationDate=_CurrentDate,SpecificConfigurationEnv=_EnvList,Target = _TypeEnv)\r\n   \t    | extend Identity = tostring(CmdletResultValue.Name)\r\n\t| extend DomainName  = tostring(CmdletResultValue.DomainName)\r\n\t| extend AutoForwardEnabled = tostring(CmdletResultValue.AutoForwardEnabled)\r\n    | extend WhenChanged = todatetime(WhenChanged)\r\n    | extend WhenCreated = todatetime(WhenCreated)\r\n;\r\nlet i=0;\r\nlet allDataRange = \r\n    ESIExchangeOnlineConfig_CL\r\n    | where TimeGenerated between (_DateCompareB .. _CurrentDateB)\r\n    | where ESIEnvironment_s == _EnvList\r\n    | where ExecutionResult_s <> \"EmptyResult\"\r\n    | where Section_s == \"RemoteDomain\"\r\n    | extend CmdletResultValue = parse_json(rawData_s)\r\n    | project TimeGenerated,CmdletResultValue,WhenChanged = todatetime(WhenChanged_t), WhenCreated=todatetime(WhenCreated_t)\r\n       | extend Identity = tostring(CmdletResultValue.Name)\r\n\t| extend DomainName  = tostring(CmdletResultValue.DomainName)\r\n\t| extend AutoForwardEnabled = tostring(CmdletResultValue.AutoForwardEnabled)\r\n    ;\r\nlet DiffAddDataP1 = allDataRange\r\n  | join kind = rightanti  (AfterData | where WhenCreated >=_DateCompareB) on WhenCreated\r\n;\r\nlet DiffAddDataP2 = allDataRange\r\n    | join kind = innerunique   (allDataRange ) on WhenCreated\r\n    | where WhenCreated >=_DateCompareB\r\n    | where bin(WhenCreated,5m)==bin(WhenChanged,5m)\r\n    | distinct  Identity,DomainName,AutoForwardEnabled,WhenChanged,WhenCreated\r\n ;\r\nlet DiffAddData = union DiffAddDataP1,DiffAddDataP2\r\n| extend Actiontype =\"Add\";\r\nlet DiffRemoveData = allDataRange\r\n    | join kind = leftanti AfterData on Identity\r\n    | extend Actiontype =\"Remove\"\r\n    | distinct  Actiontype ,Identity,DomainName,AutoForwardEnabled,WhenCreated\r\n    | project  WhenChanged=_CurrentDateB,Actiontype,Identity,DomainName,AutoForwardEnabled,WhenCreated\r\n    ;\r\nlet DiffModifData = union AfterData,allDataRange\r\n| sort by Identity,WhenChanged asc\r\n| project WhenChanged,Identity,DomainName,AutoForwardEnabled,WhenCreated\r\n| extend Identity = iff( Identity == prev(Identity) and Identity != prev(Identity) and prev(Identity) !=\"\" , strcat(\"📍 \", Identity, \" (\",prev(Identity),\"->\", Identity,\" )\"),Identity)\r\n| extend DomainName = iff( Identity == prev(Identity) and DomainName != prev(DomainName) and prev(DomainName) !=\"\" , strcat(\"📍 \", DomainName, \" (\",prev(DomainName),\"->\", DomainName,\" )\"),DomainName)\r\n| extend AutoForwardEnabled = iff( Identity == prev(Identity) and AutoForwardEnabled != prev(AutoForwardEnabled) and prev(AutoForwardEnabled) !=\"\" , strcat(\"📍 \", AutoForwardEnabled, \" (\",prev(AutoForwardEnabled),\"->\", AutoForwardEnabled,\" )\"),AutoForwardEnabled)\r\n| extend ActiontypeR =iff((Identity contains \"📍\" or DomainName contains \"📍\" or AutoForwardEnabled contains \"📍\" ), i=i + 1, i)\r\n| extend Actiontype =iff(ActiontypeR > 0, \"Modif\", \"NO\")\r\n| where ActiontypeR == 1\r\n| project WhenChanged,Actiontype,Identity,DomainName,AutoForwardEnabled,WhenCreated\r\n;\r\nunion DiffAddData, DiffRemoveData, DiffModifData\r\n| extend WhenChanged = iff (Actiontype == \"Modif\", WhenChanged, iff(Actiontype == \"Add\",WhenCreated, WhenChanged))\r\n| extend Actiontype = case(Actiontype == \"Add\", strcat(\"➕ \", Actiontype), Actiontype == \"Remove\", strcat(\"➖ \", Actiontype), Actiontype == \"Modif\", strcat(\"📍 \", Actiontype), \"N/A\")\r\n| sort by WhenChanged desc \r\n| project\r\n    WhenChanged,\r\n    Actiontype,\r\n    Identity,\r\n    DomainName,\r\n    AutoForwardEnabled,\r\n    WhenCreated",
              "size": 3,
              "showAnalytics": true,
              "title": "Display changes ( Add, Remove, modifications of parameters )",
              "showExportToExcel": true,
              "queryType": 0,
              "resourceType": "microsoft.operationalinsights/workspaces",
              "gridSettings": {
                "hierarchySettings": {
                  "treeType": 1,
                  "groupBy": [
                    "Identity"
                  ],
                  "expandTopLevel": true
                }
              }
            },
            "conditionalVisibility": {
              "parameterName": "Compare_Collect",
              "comparison": "isEqualTo",
              "value": "True"
            },
            "name": "query - 7"
          }
        ]
      },
      "conditionalVisibility": {
        "parameterName": "selected",
        "comparison": "isEqualTo",
        "value": "Transport"
      },
      "name": "Transport Security configuration"
    }
  ],
  "fromTemplateId": "sentinel-MicrosoftExchangeSecurityReview-Online",
  "$schema": "https://github.com/Microsoft/Application-Insights-Workbooks/blob/master/schema/workbook.json"
}