Descriptor:
  Name: DataSecurityAnalyst
  DisplayName: Purview - Triage, investigation, analysis, tuning
  Description: Data Security skills to query DLP events and file activities for Users and devices and correlate with other event types

SkillGroups:
  - Format: KQL
    Skills:
      - Name: DLPGetlatestDlpalertperuser
        DisplayName: Get Latest DLP alerts by user
        Description: Fetches the latest dlp events, alerts generated by the user 
        Inputs:
          - Name: User
            Description: The user associated with the alert
            Required: true
        Settings:
          Target: Defender
          Template: |-
            let user = '{{User}}';
            CloudAppEvents    
            | where ActionType has "DLPRuleMatch" or ActionType has "DLPRuleUndo" or RawEventData.PolicyMatchInfo.PolicyId <> ""
            | where ActionType !in ('FileRead','FileArchived','FileModified','FileRenamed')
            | where parse_json(tostring(parse_json(tostring(parse_json(tostring(RawEventData.PolicyDetails))[0].Rules))[0].Actions))[0] !in ('Encrypt','ExApplyBrandingTemplate')
            | where tolower(RawEventData.UserId) has tolower(user)
            | extend PolicyName_ = tostring(parse_json(tostring(RawEventData.PolicyDetails))[0].PolicyName)
            | extend SensitiveInformationTypeName_ = tostring(parse_json(tostring(parse_json(tostring(parse_json(tostring(parse_json(tostring(RawEventData.PolicyDetails))[0].Rules))[0].ConditionsMatched)).SensitiveInformation))[0].SensitiveInformationTypeName)
            | extend FileName_ = tostring(parse_json(tostring(RawEventData.SharePointMetaData)).FileName)
            | extend RuleName_ = tostring(parse_json(tostring(parse_json(tostring(RawEventData.PolicyDetails))[0].Rules))[0].RuleName)
            | extend Severity_ = tostring(parse_json(tostring(parse_json(tostring(RawEventData.PolicyDetails))[0].Rules))[0].Severity)
            | extend Attachments_ = tostring(parse_json(tostring(RawEventData.Item)).Attachments)
            | extend Recipients = strcat("To:",RawEventData.ExchangeMetaData.To, " CC:",RawEventData.ExchangeMetaData.CC," BCC:",RawEventData.ExchangeMetaData.BCC)
            | extend SharePointMetaData_SiteCollectionUrl_s  = tostring(parse_json(tostring(RawEventData.SharePointMetaData)).SiteCollectionUrl)
            | extend Documents = iff(isempty(FileName_), Attachments_, FileName_)
            | join kind = leftouter
                (
                CloudAppEvents
            | where RawEventData.Operation == "SecureLinkUsed" or RawEventData.Operation == "AddedToSecureLink"
            | extend SourceFileName = tostring(RawEventData.SourceFileName)
            | extend SharePointMetaData_SiteCollectionUrl_s = tostring(RawEventData.SiteUrl)
            | extend UserId = tostring(RawEventData.UserId)
            | extend TargetUserOrGroupName = tostring(RawEventData.TargetUserOrGroupName)
                        | summarize by SharePointMetaData_SiteCollectionUrl_s,SourceFileName,TargetUserOrGroupName
                        | summarize TargetUserOrGroupName = make_list(strcat(TargetUserOrGroupName)) by SharePointMetaData_SiteCollectionUrl_s,SourceFileName
                        | summarize take_any(TargetUserOrGroupName) by SourceFileName,SharePointMetaData_SiteCollectionUrl_s
            |project SourceFileName, SharePointMetaData_SiteCollectionUrl_s, TargetUserOrGroupName
                )
                on SharePointMetaData_SiteCollectionUrl_s   
            | extend TargetUsers = iff(isnotempty(tostring(TargetUserOrGroupName)), tostring(TargetUserOrGroupName), Recipients)
            | extend Subject = tostring(parse_json(tostring(RawEventData.ExchangeMetaData)).Subject)
            | extend PolicyName_EndPoint = tostring(parse_json(tostring(RawEventData.PolicyMatchInfo)).PolicyName)
            | extend PolicyName = iff(isempty(PolicyName_), PolicyName_EndPoint, PolicyName_)   
            | extend Workload = tostring(RawEventData.Workload)
            | extend Object = tostring(RawEventData.ObjectId)
            | join kind=leftouter
            (
            CloudAppEvents
            | where RawEventData.Workload has "Endpoint"
            | extend SensitiveInfoTypeName_ = tostring(parse_json(tostring(RawEventData.SensitiveInfoTypeData))[0].SensitiveInfoTypeName)
            | where SensitiveInfoTypeName_ <> ""
            | extend EndPointFile = tostring(RawEventData.ObjectId)
            | extend PolicyName = tostring(parse_json(tostring(RawEventData.PolicyMatchInfo)).PolicyName)
            | project EndPointFile,SensitiveInfoTypeName_,PolicyName
            )
            on $left.Object == $right.EndPointFile
            | extend Documents = iff(isempty(Documents), EndPointFile, Documents)
            | extend SensitiveInformationType = iff(isempty(SensitiveInformationTypeName_), SensitiveInfoTypeName_, SensitiveInformationTypeName_)
            | extend EndpointOperation_ = tostring(parse_json(tostring(RawEventData.EndpointMetaData)).EndpointOperation)
            | extend TargetDomain = tostring(parse_json(tostring(RawEventData.EndpointMetaData)).TargetDomain)
            | extend Target = iff(isempty(tostring(TargetDomain)), TargetUsers, tostring(TargetDomain))   
            | project  Timestamp,ActionType,Workload,PolicyName,SensitiveInformationType,Documents,Target,Subject,Severity_
            | summarize arg_max(Timestamp, *) by Workload,PolicyName,SensitiveInformationType,Documents,Target
            | sort by Timestamp

      - Name: DLPgetAllDlpalerts
        DisplayName: Get all dlp alerts so that they can be analyzed
        Description: Fetches all dlp alerts so that they can be analyzed
        Inputs:
          - Name: workload
            Description: Specify the workload for which the alerts are to be fetched
            Required: false
        Settings:
          Target: Defender
          Template: |-
            let workload = '{{workload}}';
                        let EndPointAction = datatable(ActionName: string, Action: int) [
                'None', '0',
                'Audit', '1',
                'Warn', '2',
                'WarnAndBypass', '3',
                'Block', '4',
                'Allow', '5'
            ];
            CloudAppEvents 
            //| search incident 
            | where ActionType has 'DLPRuleMatch' or ActionType has "DLPRuleUndo" or RawEventData.PolicyMatchInfo.PolicyId <> ""
            | where ActionType !in ('FileRead','FileArchived','FileModified','FileRenamed')
            | where RawEventData.Workload has workload
            | extend CreationTime = tostring(RawEventData.CreationTime)
            | extend User = tolower(RawEventData.UserId)
            //| project RawEventData,RawEventData2,User,RawEventData2.ObjectId,RawEventData.Workload,Timestamp
            | where parse_json(tostring(parse_json(tostring(parse_json(tostring(RawEventData.PolicyDetails))[0].Rules))[0].Actions))[0] !in ('Encrypt','ExApplyBrandingTemplate')
            | extend PolicyName_ = tostring(parse_json(tostring(RawEventData.PolicyDetails))[0].PolicyName)
            | extend Action = tostring(parse_json(tostring(parse_json(tostring(parse_json(tostring(RawEventData.PolicyDetails))[0].Rules))[0].Actions)))
            | extend RuleName_ = tostring(parse_json(tostring(parse_json(tostring(RawEventData.PolicyDetails))[0].Rules))[0].RuleName)
            | extend classifiermatch = tostring(parse_json(tostring(parse_json(tostring(parse_json(tostring(parse_json(tostring(RawEventData.PolicyDetails))[0].Rules))[0].ConditionsMatched)).SensitiveInformation)))
            | extend PolicyName_ = tostring(parse_json(tostring(RawEventData.PolicyDetails))[0].PolicyName)
            | extend SensitiveInformationTypeName_ = tostring(parse_json(tostring(parse_json(tostring(parse_json(tostring(parse_json(tostring(RawEventData.PolicyDetails))[0].Rules))[0].ConditionsMatched)).SensitiveInformation))[0].SensitiveInformationTypeName)
            | extend FileName_ = tostring(parse_json(tostring(RawEventData.SharePointMetaData)).FileName)
            | extend RuleName_ = tostring(parse_json(tostring(parse_json(tostring(RawEventData.PolicyDetails))[0].Rules))[0].RuleName)
            | extend Severity_ = tostring(parse_json(tostring(parse_json(tostring(RawEventData.PolicyDetails))[0].Rules))[0].Severity)
            | extend Attachments_ = tostring(parse_json(tostring(RawEventData.Item)).Attachments)
            | extend Recipients = strcat('To:',RawEventData.ExchangeMetaData.To, ' CC:',RawEventData.ExchangeMetaData.CC,' BCC:',RawEventData.ExchangeMetaData.BCC)
            | extend SharePointMetaData_SiteCollectionUrl_s  = tostring(parse_json(tostring(RawEventData.SharePointMetaData)).SiteCollectionUrl)
            | extend Documents = iff(isempty(FileName_), Attachments_, FileName_)
            | extend endpointdata = (parse_json(RawEventData.EndpointMetaData))
            | extend EndPointAction = toint(RawEventData.EnforcementMode)
            | extend EndPointFile = tostring(RawEventData.ObjectId)
            | join kind= leftouter
                (
                EndPointAction
                )
                on $left.EndPointAction==$right.Action
                | extend Action = iff(isempty(Action), tolower(ActionName), Action)
                | extend endpointclassifiermatch = endpointdata.SensitiveInfoTypeData
                | extend Documents = iff(isempty(Documents), EndPointFile, Documents)
                | mv-expand RawEventData.SensitiveInfoTypeData
                | extend SensitiveInfoTypeName_ = tostring(RawEventData_SensitiveInfoTypeData.SensitiveInfoTypeName)
            | extend SensitiveInformationType = iff(isempty(SensitiveInformationTypeName_), SensitiveInfoTypeName_, SensitiveInformationTypeName_)
            | extend EndpointOperation_ = ActionType
            | extend TargetDomain = tostring(parse_json(tostring(RawEventData.EndpointMetaData)).TargetDomain)
            | extend Subject = tostring(parse_json(tostring(RawEventData.ExchangeMetaData)).Subject)
            | project Workload = tostring(RawEventData.Workload),Action,User,SensitiveInformationType,EndpointOperation_,TargetDomain,Subject,Documents,Recipients,Timestamp
            | summarize arg_max(Timestamp, *) by User,SensitiveInformationType,Subject,EndpointOperation_
            | sort by Timestamp

      - Name: DLPgetalertbyPolicy
        DisplayName: Get the DLP alerts by policy
        Description: Fetches all dlp alerts associated with a specific policy
        Inputs:
          - Name: policy
            Description: Specify the policy for which the alerts are to be fetched
            Required: false
        Settings:
          Target: Defender
          Template: |-
            let policyvar = '{{policy}}';
            let workload = '';
                        let EndPointAction = datatable(ActionName: string, Action: int) [
                'None', '0',
                'Audit', '1',
                'Warn', '2',
                'WarnAndBypass', '3',
                'Block', '4',
                'Allow', '5'
            ];
            CloudAppEvents 
            //| search incident 
            | where ActionType has 'DLPRuleMatch' or ActionType has "DLPRuleUndo" or RawEventData.PolicyMatchInfo.PolicyId <> ""
            | where ActionType !in ('FileRead','FileArchived','FileModified','FileRenamed')
            | where RawEventData.Workload has workload
            | extend CreationTime = tostring(RawEventData.CreationTime)
            | extend User = tolower(RawEventData.UserId)
            | where parse_json(tostring(parse_json(tostring(parse_json(tostring(RawEventData.PolicyDetails))[0].Rules))[0].Actions))[0] !in ('Encrypt','ExApplyBrandingTemplate')
            | extend Action = tostring(parse_json(tostring(parse_json(tostring(parse_json(tostring(RawEventData.PolicyDetails))[0].Rules))[0].Actions)))
            | extend PolicyName_ = tostring(parse_json(tostring(RawEventData.PolicyDetails))[0].PolicyName)
            | extend PolicyNameEP = tostring(parse_json(tostring(RawEventData.MatchedPolicies))[0].PolicyName)
            | extend PolicyName = iff(isempty(PolicyName_),PolicyNameEP,PolicyName_)
            | where PolicyName has policyvar
            | extend RuleName_ = tostring(parse_json(tostring(parse_json(tostring(RawEventData.PolicyDetails))[0].Rules))[0].RuleName)
            | extend classifiermatch = tostring(parse_json(tostring(parse_json(tostring(parse_json(tostring(parse_json(tostring(RawEventData.PolicyDetails))[0].Rules))[0].ConditionsMatched)).SensitiveInformation)))
            | extend SensitiveInformationTypeName_ = tostring(parse_json(tostring(parse_json(tostring(parse_json(tostring(parse_json(tostring(RawEventData.PolicyDetails))[0].Rules))[0].ConditionsMatched)).SensitiveInformation))[0].SensitiveInformationTypeName)
            | extend FileName_ = tostring(parse_json(tostring(RawEventData.SharePointMetaData)).FileName)
            | extend RuleName_ = tostring(parse_json(tostring(parse_json(tostring(RawEventData.PolicyDetails))[0].Rules))[0].RuleName)
            | extend Severity_ = tostring(parse_json(tostring(parse_json(tostring(RawEventData.PolicyDetails))[0].Rules))[0].Severity)
            | extend Attachments_ = tostring(parse_json(tostring(RawEventData.Item)).Attachments)
            | extend Recipients = strcat('To:',RawEventData.ExchangeMetaData.To, ' CC:',RawEventData.ExchangeMetaData.CC,' BCC:',RawEventData.ExchangeMetaData.BCC)
            | extend SharePointMetaData_SiteCollectionUrl_s  = tostring(parse_json(tostring(RawEventData.SharePointMetaData)).SiteCollectionUrl)
            | extend Documents = iff(isempty(FileName_), Attachments_, FileName_)
            | extend endpointdata = (parse_json(RawEventData.EndpointMetaData))
            | extend EndPointAction = toint(RawEventData.EnforcementMode)
            | extend EndPointFile = tostring(RawEventData.ObjectId)
            | join kind= leftouter
                (
                EndPointAction
                )
                on $left.EndPointAction==$right.Action
                | extend Action = iff(isempty(Action), tolower(ActionName), Action)
                | extend endpointclassifiermatch = endpointdata.SensitiveInfoTypeData
                | extend Documents = iff(isempty(Documents), EndPointFile, Documents)
                | mv-expand RawEventData.SensitiveInfoTypeData
                | extend SensitiveInfoTypeName_ = tostring(RawEventData_SensitiveInfoTypeData.SensitiveInfoTypeName)
            | extend SensitiveInformationType = iff(isempty(SensitiveInformationTypeName_), SensitiveInfoTypeName_, SensitiveInformationTypeName_)
            | extend EndpointOperation_ = ActionType
            | extend TargetDomain = tostring(parse_json(tostring(RawEventData.EndpointMetaData)).TargetDomain)
            | extend Subject = tostring(parse_json(tostring(RawEventData.ExchangeMetaData)).Subject)
            | project Workload = tostring(RawEventData.Workload),Action,User,SensitiveInformationType,EndpointOperation_,TargetDomain,Subject,Documents,Recipients,PolicyName,Timestamp
            | summarize arg_max(Timestamp, *) by User,SensitiveInformationType,Subject,PolicyName
            | sort by Timestamp

      - Name: DLPgetFileactivity
        DisplayName: Get the file activity of the specified file 
        Description: Fetches the file activity of the latest file including labels and sensitive information
        Inputs:
          - Name: document
            Description: The file activity associated with the specific file
            Required: true
        Settings:
          Target: Defender
          Template: |-
            let document = '{{document}}';
            CloudAppEvents
            | extend sit = parse_json(tostring(parse_json(tostring(parse_json(tostring(parse_json(tostring(RawEventData.PolicyDetails))[0].Rules))[0].ConditionsMatched)).SensitiveInformation))
            | mv-expand sit
            | where sit.Location has document or tostring(parse_json(tostring(RawEventData.Item)).Attachments) has document or url_decode(ObjectName) has document or RawEventData.ObjectId has document  or RawEventData.ItemName has document or RawEventData.DestinationFileName has document   
            | extend User = tostring(RawEventData.UserId)
            | extend LabelGUID1 = parse_json(tostring(RawEventData.SensitivityLabelEventData)).SensitivityLabelId
                | extend LabelGUID2 = iff(isempty(tostring(RawEventData.LabelId)), LabelGUID1, tostring(RawEventData.LabelId))
                | extend LabelGUID3 = iff(isempty(tostring(RawEventData.SensitivityLabelId)), LabelGUID2, tostring(RawEventData.SensitivityLabelId))
                | extend OldSensitivityLabelId = tostring(parse_json(tostring(RawEventData.SensitivityLabelEventData)).OldSensitivityLabelId)
                | extend LabelGUID = iff(isempty(tostring(LabelGUID3)),OldSensitivityLabelId, tostring(LabelGUID3))  
            | mv-expand PolicyDetails = RawEventData.PolicyDetails
            | mv-expand Rules = PolicyDetails.Rules
            | mv-expand Sensitive = Rules.ConditionsMatched.SensitiveInformation   
            | extend sit = parse_json(tostring(RawEventData.SensitiveInfoTypeData)) 
            | mv-expand sit              
            | extend sit = iff(isempty(sit.SensitiveInfoTypeName),Sensitive.SensitiveInformationTypeName,sit.SensitiveInfoTypeName)
            | extend SensitiveInfoTypeName = tostring(sit) 
            | project Timestamp,Activity=ActionType,User,CountryCode,LabelGUID,SensitiveInfoTypeName
            | sort by Timestamp       

      - Name: DLPgetEndpointactivity
        DisplayName: Get the sensitive file activity of the specified Device
        Description: Fetches the sensitive file activity happening on the Device
        Inputs:
          - Name: device
            Description: The file activity associated with the specific device
            Required: true
        Settings:
          Target: Defender
          Template: |-
            let devicevar = '{{device}}';
            let AppEvents = (CloudAppEvents 
            | where parse_json(tostring(RawEventData.SensitiveInfoTypeData)) != "" 
            | where parse_json(tostring(RawEventData.SensitiveInfoTypeData)) != "[]" 
            | extend sit = parse_json(tostring(RawEventData.SensitiveInfoTypeData)) 
            | mv-expand sit 
            | extend UserId = tolower(RawEventData.UserId) 
            | extend SensitiveInfoTypeName = tostring(sit.SensitiveInfoTypeName) 
            | extend document = tostring(RawEventData.ObjectId) 
            ); 
            AppEvents 
            | where tolower(RawEventData.DeviceName) == tolower(devicevar) 
            | extend ObjectId = tostring(RawEventData.ObjectId) 
            | extend DeviceName = tostring(RawEventData.DeviceName) 
            | extend Application = tostring(RawEventData.Application) 
            | summarize count = count() by document,Application,SensitiveInfoTypeName,ActionType,DeviceName,CountryCode 
            |order by ActionType

      - Name: DLPgetSiteCollectionActivity
        DisplayName: Get the SharePoint site collection or library activity of the specified collection
        Description: Fetches the SharePoint site collection or library activity of the selected collection
        Inputs:
          - Name: sitecollection
            Description: The site or library activity associated with the specified collection
            Required: true
        Settings:
          Target: Defender
          Template: |-
            let sitecollection = '{{sitecollection}}';
            CloudAppEvents 
            | where RawEventData.Workload == "OneDrive" or RawEventData.Workload == "SharePoint" 
            | where RawEventData.ObjectId has sitecollection 
            | extend Operation = tostring(RawEventData.Operation) 
            //Filter to a smaller set of operations, add additional operations as needed 
            | where Operation  in ('FileAccessed','FilePreviewed','FileModifiedExtended','FileSensitivityLabelApplied','FileModified','FileUploaded','FileDownloaded','FileRenamed','AddedToSecureLink','SharingSet','SecureLinkCreated','SharingInheritanceBroken','FileSensitivityLabelChanged','CompanyLinkUsed','CompanyLinkCreated','SharingRevoked','FileSyncDownloadedFull','AddedToGroup','FileSensitivityLabelRemoved')
            | extend Account = tostring(RawEventData.UserId) 
            | extend SharePointMetaData_SiteCollectionUrl_s =  tostring((RawEventData.SharePointMetaData.SiteCollectionUrl)) 
            | extend FilePathUrl_ = url_decode(tostring(parse_json(tostring(RawEventData.SharePointMetaData)).FilePathUrl)) 
            | extend SourceRelativeUrl = tostring(RawEventData.SourceRelativeUrl) 
            | extend SourceFileName_ = tostring(RawEventData.SourceFileName) 
            | extend TargetUserOrGroupName = tostring(RawEventData.TargetUserOrGroupName) 
            | summarize 
                by 
                Timestamp, 
                Operation, 
                SourceFileName_, 
                Account, 
                SourceRelativeUrl, 
                TargetUserOrGroupName 
            | sort by Timestamp 
    
      - Name: DLPTeamsDetectionsUser
        DisplayName: Get all the meetings, chats and channel messages that triggered an alert for a user or recipient
        Description: Fetches all the meetings, chats and channel messages that triggered an alert for a user or recipient
        Inputs: 
          - Name: Recipient 
            Description: The recipient associated with the alert 
            Required: false 
          - Name: User
            Description: the user associated with the information 
            Required: false 
        Settings:
          Target: Defender
          Template: |-
            let Recipient = '{{Recipient}}';
            let user = '{{User}}';
              let TeamsMeeting = (
              CloudAppEvents
              | where Application == 'Microsoft Teams'
              | where ActionType == 'DLPRuleMatch'
              | extend UserId_ = tostring(RawEventData.UserId)
              | extend Workload_ = tostring(RawEventData.Workload)
              | extend ObjectId_ = tostring(RawEventData.ObjectId)
              | extend MessageId_ = ObjectId_
              | join kind=leftouter 
                  ( CloudAppEvents 
                      | where RawEventData.Name == 'policyViolation'
                      | extend MessageId_ = tostring(RawEventData.MessageId)
                      | extend MeetingDetailId_ = tostring(RawEventData.MeetingDetailId)
                      )
                      on MessageId_
                      | extend ChatThreadId_ = tostring(RawEventData1.ItemName)
              | join kind=inner   
                  ( CloudAppEvents
                      | where RawEventData.Operation == 'MeetingDetail'
                      | extend ChatThreadId_ = tostring(RawEventData.ChatThreadId)
                      | extend meetid = tostring(RawEventData.Id)
                      ) on ChatThreadId_
                      | extend Meeting = tostring(parse_json(tostring(parse_json(tostring(RawEventData.ExchangeMetaData)).To))[0])
                      | extend PolicyName = tostring(parse_json(tostring(RawEventData.PolicyDetails))[0].PolicyName)
                      | extend RuleName = tostring(parse_json(tostring(parse_json(tostring(RawEventData.PolicyDetails))[0].Rules))[0].RuleName)
                      | extend SensitiveInformationTypeName = tostring(parse_json(tostring(parse_json(tostring(parse_json(tostring(parse_json(tostring(RawEventData.PolicyDetails))[0].Rules))[0].ConditionsMatched)).SensitiveInformation))[0].SensitiveInformationTypeName)
              | project meetid,Meeting,PolicyName,RuleName,SensitiveInformationTypeName,UserId_
              | join kind=inner
                  (    
                  CloudAppEvents
                  | where RawEventData.Operation == 'MeetingParticipantDetail'
                  | extend meetid = tostring(RawEventData.MeetingDetailId)
                  )
                  on meetid
              | extend UPN = tostring(parse_json(tostring(RawEventData.Attendees))[0].UPN)
              | extend RecipientType = tostring(parse_json(tostring(RawEventData.Attendees))[0].RecipientType)
              //| where RecipientType startswith 'Guest'
              | extend Type = "TeamsMeeting"
              | project Type,UPN,RecipientType,Meeting,PolicyName,RuleName,SensitiveInformationTypeName,UserId_);
              let channel =( 
              CloudAppEvents
              | where Application == 'Microsoft Teams'
              | where ActionType == 'DLPRuleMatch'
              | extend UserId_ = tostring(RawEventData.UserId)
              | extend TeamName = tolower(parse_json(tostring(parse_json(tostring(RawEventData.ExchangeMetaData)).To))[0])
              | extend PolicyName = tostring(parse_json(tostring(RawEventData.PolicyDetails))[0].PolicyName)
                      | extend RuleName = tostring(parse_json(tostring(parse_json(tostring(RawEventData.PolicyDetails))[0].Rules))[0].RuleName)
                      | extend SensitiveInformationTypeName = tostring(parse_json(tostring(parse_json(tostring(parse_json(tostring(parse_json(tostring(RawEventData.PolicyDetails))[0].Rules))[0].ConditionsMatched)).SensitiveInformation))[0].SensitiveInformationTypeName)
              | join kind=inner 
              (
              CloudAppEvents
              | where Application == 'Microsoft Teams'
              | extend TeamName = tolower(RawEventData.TeamName)
              | extend UPN = tostring(parse_json(tostring(RawEventData.Members))[0].UPN)
              | extend GroupId = tostring(RawEventData.AADGroupId)
              | extend HasGuestUsers = tostring(parse_json(tostring(RawEventData.ParticipantInfo)).HasGuestUsers)
              | extend HasUnauthenticatedUsers = tostring(parse_json(tostring(RawEventData.ParticipantInfo)).HasUnauthenticatedUsers)
              ) on TeamName
              | where HasGuestUsers == 'true' or HasUnauthenticatedUsers == 'true'
              | project TeamName,ActionType,HasGuestUsers,HasUnauthenticatedUsers,UPN,PolicyName,RuleName,SensitiveInformationTypeName,UserId_
              | extend Type = "TeamChannel");
              let individual = (
              CloudAppEvents
              | where Application == 'Microsoft Teams'
              | where ActionType has 'DLPRuleMatch'
              | extend UPN = tostring(parse_json(tostring(parse_json(tostring(RawEventData.ExchangeMetaData)).To))[0])
              | where UPN matches regex '(\\S*@\\S*.\\S*)'
              | extend UserId_ = tostring(RawEventData.UserId)
              | extend TeamName = tolower(parse_json(tostring(parse_json(tostring(RawEventData.ExchangeMetaData)).To))[0])
              | extend PolicyName = tostring(parse_json(tostring(RawEventData.PolicyDetails))[0].PolicyName)
                      | extend RuleName = tostring(parse_json(tostring(parse_json(tostring(RawEventData.PolicyDetails))[0].Rules))[0].RuleName)
                      | extend SensitiveInformationTypeName = tostring(parse_json(tostring(parse_json(tostring(parse_json(tostring(parse_json(tostring(RawEventData.PolicyDetails))[0].Rules))[0].ConditionsMatched)).SensitiveInformation))[0].SensitiveInformationTypeName)
                      | extend Type = "Individual");
                union channel,TeamsMeeting,individual
                | where UserId_ has user
                | where UPN has Recipient
                | extend Name = iff(isempty(TeamName),Meeting,TeamName)
                | summarize by Type,User=UserId_,Name,Target=UPN,PolicyName,SensitiveInformationTypeName

      - Name: DLPFilesSharedwithUser
        DisplayName: Get the file and shared user information 
        Description: Fetches all information associated with Shared information and user 
        Inputs: 
          - Name: document 
            Description: the file associated with the user activity 
            Required: true 
          - Name: User
            Description: the user associated with the information 
            Required: false 
        Settings:
          Target: Defender
          Template: |-
            let document = '{{document}}';
            let user = '{{User}}';
            let DLP = (CloudAppEvents
              | where RawEventData.Workload in ('SharePoint', 'OneDrive')
              | where ActionType == "DLPRuleMatch" 
              | extend FilePathUrl_ = url_decode(tostring(RawEventData.SharePointMetaData.FilePathUrl))
              | extend path = parse_path(FilePathUrl_)
              | where path.Filename has document
              | extend DirectoryPath = tostring(path.DirectoryPath)
              | summarize by DirectoryPath );
              let officedata = (
              CloudAppEvents
              | where RawEventData.Operation == "SecureLinkUsed" or RawEventData.Operation == "AddedToSecureLink"
              | extend ObjectId_ = tostring(RawEventData.ObjectId)
              | where ObjectId_ has_any (DLP)
              | extend SharePointMetaData_SiteCollectionUrl = tostring(RawEventData.SiteUrl)
              | extend SharePointMetaData_FileName = tostring((RawEventData.SourceFileName))
              | extend Account = tostring(RawEventData.UserId)
              | extend Targetsplit = split(Account, "#")
              | extend TargetUserOrGroupName = iff(isempty(RawEventData.TargetUserOrGroupName), Targetsplit[1], RawEventData.TargetUserOrGroupName)
              //Exclude internal domains if required
              //| where TargetUserOrGroupName !has "mydom1.com"
              | extend TargetUserOrGroupName = tolower(TargetUserOrGroupName)
              | summarize
                  by
                  SharePointMetaData_FileName,
                  SharePointMetaData_SiteCollectionUrl,
                  TargetUserOrGroupName,
                  ObjectId_,
                  Account);
              let dlpmain = (
              CloudAppEvents
              | where ActionType == "DLPRuleMatch"
              | where RawEventData.Workload == "OneDrive" or RawEventData.Workload == "SharePoint"
              | extend FilePathUrl_ = url_decode(tostring(RawEventData.SharePointMetaData.FilePathUrl))
              | extend path = parse_path(FilePathUrl_)
              | where path.Filename has document
              | extend Account = tostring(RawEventData.UserId)
              | where Account has user
              | extend ObjectId_ = url_decode(tostring(ObjectName))
              | extend SharePointMetaData_SiteCollectionUrl =  tostring((RawEventData.SharePointMetaData.SiteCollectionUrl))
              | where tolower(RawEventData.UserId) == tolower(Account)
              | where RawEventData.Workload in ('SharePoint', 'OneDrive')
              | extend SourceFileName = tostring(RawEventData.SourceFileName)
              );
              let folder = (dlpmain
              | join kind = leftouter
                  (officedata
                      | summarize
                      by
                      SharePointMetaData_SiteCollectionUrl,
                      SharePointMetaData_FileName,
                      TargetUserOrGroupName,
                      ObjectId_
                  | summarize TargetUserOrGroupName = make_list(strcat(TargetUserOrGroupName))
                      by
                      ObjectId_,
                      SharePointMetaData_SiteCollectionUrl,
                      SharePointMetaData_FileName
                  | summarize take_any(TargetUserOrGroupName)
                      by
                      ObjectId_,
                      SharePointMetaData_SiteCollectionUrl,
                      SharePointMetaData_FileName
                  | join kind = leftouter
                      (
                      officedata
                      | summarize
                          by
                          SharePointMetaData_SiteCollectionUrl,
                          SharePointMetaData_FileName,
                          TargetUserOrGroupName,
                          ObjectId_
                      | extend Domsplit = split(TargetUserOrGroupName, "@")
                      | extend domain = Domsplit[1]
                      | summarize TargetDomain = make_list(strcat(domain)) by SharePointMetaData_FileName, ObjectId_
                      | summarize take_any(TargetDomain) by SharePointMetaData_FileName, ObjectId_
                      )
                      on ObjectId_
                  )
                  on ObjectId_
              );
              let files = (folder
              //| where TargetUserOrGroupName == ""
              | join kind = leftouter
                  (officedata
                  | summarize TargetUserOrGroupName = make_list(strcat(TargetUserOrGroupName)) by SharePointMetaData_FileName, SharePointMetaData_SiteCollectionUrl
                  | summarize take_any(TargetUserOrGroupName) by SharePointMetaData_FileName, SharePointMetaData_SiteCollectionUrl
                  | join kind = leftouter
                      (
                      officedata
                      | summarize
                          by
                          SharePointMetaData_SiteCollectionUrl,
                          SharePointMetaData_FileName,
                          TargetUserOrGroupName
                      | extend Domsplit = split(TargetUserOrGroupName, "@")
                      | extend domain = Domsplit[1]
                      | summarize TargetDomain = make_list(strcat(domain)) by SharePointMetaData_FileName
                      | summarize take_any(TargetDomain) by SharePointMetaData_FileName
                      )
                      on SharePointMetaData_FileName
                  )
                  on SharePointMetaData_FileName, SharePointMetaData_SiteCollectionUrl
              | extend TargetUserOrGroupName = TargetUserOrGroupName1
              | extend TargetDomain = TargetDomain1
              | where TargetUserOrGroupName != ""
              );
              union folder, files
              | extend FileName = tostring(parse_json(tostring(RawEventData.SharePointMetaData)).FileName)
              | summarize arg_max(Timestamp, *) by ObjectId_, Account, tostring(RawEventData.Id)
              | extend FileNameEncoded = url_encode(FileName)
              | extend MDALink = (strcat('https://security.microsoft.com/cloudapps/files?filename=eq(',FileNameEncoded,')')) //Use this link to view older operations directly from Microsoft Defender for Cloud Apps
              | project Timestamp,FileName,TargetUser= TargetUserOrGroupName,SiteCollection = ObjectId_
              | sort by Timestamp

      - Name: DLPAnomalies
        DisplayName: Get DLP anomalies or outliers from the log stream
        Description: Fetches anomalies or outliers from the log stream
        Settings:
          Target: Defender
          Template: |-
            CloudAppEvents
            | where ActionType == "DlpRuleMatch"
            | extend UserId = tostring(RawEventData.UserId)
            | summarize EventCount=count() by UserId, bin(Timestamp,30m)
            | order by Timestamp
            | summarize EventCount=make_list(EventCount),TimeGenerated=make_list(Timestamp) by UserId
            | extend outliers=series_decompose_anomalies(EventCount)
            | mv-expand TimeGenerated, EventCount, outliers
            | where outliers == 1
            | summarize aggregate=sum(todecimal(EventCount)) by UserId

      - Name: DLPExchangeTuning
        DisplayName: Receive DLP tuning recommendations for Exchange
        Description: This skill provides tuning and optimization recommendations for DLP policies in Exchange
        Settings:
          Target: Defender
          Template: |-
            let Exchange = (
            CloudAppEvents 
            | where ActionType has 'DLPRuleMatch' 
            | where RawEventData.Workload has 'Exchange'
            | extend To = todynamic(parse_json(tostring(parse_json(RawEventData.ExchangeMetaData).To)))
            | extend PolicyName = tostring(parse_json(tostring(RawEventData.PolicyDetails))[0].PolicyName)
            | extend SensitiveInformationTypeName = tostring(parse_json(tostring(parse_json(tostring(parse_json(tostring(parse_json(tostring(RawEventData.PolicyDetails))[0].Rules))[0].ConditionsMatched)).SensitiveInformation))[0].SensitiveInformationTypeName));
            let To = (
            Exchange
            | extend Type = 'To'
            | extend To = todynamic(parse_json(tostring(parse_json(RawEventData.ExchangeMetaData).To)))
            | mv-expand To
            | summarize count() by tostring(To),PolicyName,tostring(RawEventData.Workload),Type,SensitiveInformationTypeName
            | take 25);
            let From = (
            Exchange 
            | extend Type = 'From'
            | extend From = tostring(parse_json(tostring(RawEventData.ExchangeMetaData)).From)
            | summarize count() by From,PolicyName,tostring(RawEventData.Workload),Type,SensitiveInformationTypeName
            | take 25 );
            let Location = (
            Exchange
            | extend Type = 'MatchLocation'
            | extend Location = tostring(parse_json(tostring(parse_json(tostring(parse_json(tostring(parse_json(tostring(RawEventData.PolicyDetails))[0].Rules))[0].ConditionsMatched)).SensitiveInformation))[0].Location)
            | extend PolicyName = tostring(parse_json(tostring(RawEventData.PolicyDetails))[0].PolicyName)
            | summarize count() by Location,PolicyName,SensitiveInformationTypeName,tostring(RawEventData.Workload),Type
            |take 25 );
            let Sensitive = (
            Exchange
            | extend Type = 'SensitiveInformationType' 
            | extend PolicyName = tostring(parse_json(tostring(RawEventData.PolicyDetails))[0].PolicyName)
            | summarize count() by SensitiveInformationTypeName,PolicyName,tostring(RawEventData.Workload),Type
            |take 25 );
            let domains = (
            Exchange
            | extend Type = 'Targetdomains'
            | extend To = todynamic(parse_json(tostring(parse_json(RawEventData.ExchangeMetaData).To)))
            | mv-expand To
            | extend user = split(To,'@')
            | summarize count() by Targetdomain=tostring(user[1]),PolicyName,tostring(RawEventData.Workload),Type,SensitiveInformationTypeName
            | take 25 );
            let subject = (
            Exchange
            | extend Type = 'subject' 
            | extend Subject = tostring(parse_json(tostring(RawEventData.ExchangeMetaData)).Subject)
            | summarize count() by Subject,PolicyName,tostring(RawEventData.Workload),Type,SensitiveInformationTypeName
            | take 25);
            union To, From, Location, Sensitive,domains,subject

      - Name: DLPSharePointTuning
        DisplayName: Receive DLP tuning recommendations for SharePoint and OneDrive
        Description: This skill provides tuning recommendations for DLP policies in SharePoint and OneDrive
        Settings:
          Target: Defender
          Template: |-
                let SPO = (
                CloudAppEvents
                | where ActionType == 'DLPRuleMatch'
                | where RawEventData.Workload == 'OneDrive' or RawEventData.Workload == 'SharePoint'
                | extend Account = tostring(RawEventData.UserId)
                | extend SharePointMetaData_SiteCollectionUrl_s =  tostring((RawEventData.SharePointMetaData.SiteCollectionUrl))
                | extend PolicyName = tostring(parse_json(tostring(RawEventData.PolicyDetails))[0].PolicyName)
                | extend FileName = tostring(parse_json(tostring(RawEventData.SharePointMetaData)).FileName)
                | extend SensitiveInformationTypeName = tostring(parse_json(tostring(parse_json(tostring(parse_json(tostring(parse_json(tostring(RawEventData.PolicyDetails))[0].Rules))[0].ConditionsMatched)).SensitiveInformation))[0].SensitiveInformationTypeName)
                | join kind = inner
                    (
                    CloudAppEvents
                | where RawEventData.Operation == 'SecureLinkUsed' or RawEventData.Operation == 'AddedToSecureLink'
                | extend SourceFileName = tostring(RawEventData.SourceFileName)
                | extend SharePointMetaData_SiteCollectionUrl_s = tostring(RawEventData.SiteUrl)
                | extend UserId = tostring(RawEventData.UserId)
                | extend TargetUserOrGroupName = tostring(RawEventData.TargetUserOrGroupName)
                | extend Sharedwith= iff(isempty(TargetUserOrGroupName), UserId, TargetUserOrGroupName) 
                |project 
                        SourceFileName,
                        SharePointMetaData_SiteCollectionUrl_s,
                        TargetUserOrGroupName,
                        Sharedwith
                    )
                    on SharePointMetaData_SiteCollectionUrl_s
                    | project Timestamp,Account,SharePointMetaData_SiteCollectionUrl_s, SourceFileName, Sharedwith,RawEventData,PolicyName,FileName,SensitiveInformationTypeName
                    | sort by Timestamp);
                    let Account = (
                    SPO
                    | summarize count() by Account
                    | extend Type = 'Account'
                    | take 25);
                        let Target = (
                    SPO
                    | extend Type = 'Target'
                    | summarize count() by Targetuser=Sharedwith,Type
                    | take 25);
                    let TargetDom = (
                    SPO
                    | extend Type = 'domains'
                    | extend TargetDom = split(Sharedwith,'@')
                    | summarize count() by targetDomain=tostring(TargetDom[1]),Type
                    | take 25);
                    let TopSites = (
                    SPO
                    | extend Type = 'TopSites'
                    | summarize count() by SharePointMetaData_SiteCollectionUrl_s,Type,SensitiveInformationTypeName
                    | take 25);
                    let TopDocs = (
                    SPO
                    | extend Type = 'TopDocs'
                    | summarize count() by FileName,Type,SensitiveInformationTypeName
                    | take 25);
                    let TopSIT = (
                    SPO
                    | extend Type = 'TopSIT'
                    | summarize count() by Type,SensitiveInformationTypeName
                    | take 25);
                    union TargetDom,Account,Target,TopSites,TopDocs,TopSIT

      - Name: DLPTeamsTuning
        DisplayName: Receive DLP tuning recommendations for Teams
        Description: This skill provides tuning recommendations for DLP policies in Teams
        Settings:
          Target: Defender
          Template: |-
              let TeamsMeeting = (
              CloudAppEvents
              | where Application == 'Microsoft Teams'
              | where ActionType == 'DLPRuleMatch'
              | extend UserId_ = tostring(RawEventData.UserId)
              | extend Workload_ = tostring(RawEventData.Workload)
              | extend ObjectId_ = tostring(RawEventData.ObjectId)
              | extend MessageId_ = ObjectId_
              | join kind=inner 
                  ( CloudAppEvents 
                      | where RawEventData.Name == 'policyViolation'
                      | extend MessageId_ = tostring(RawEventData.MessageId)
                      | extend MeetingDetailId_ = tostring(RawEventData.MeetingDetailId)
                      )
                      on MessageId_
                      | extend ChatThreadId_ = tostring(RawEventData1.ItemName)
              | join kind=inner 
                  ( CloudAppEvents
                      | where RawEventData.Operation == 'MeetingDetail'
                      | extend ChatThreadId_ = tostring(RawEventData.ChatThreadId)
                      | extend meetid = tostring(RawEventData.Id)
                      ) on ChatThreadId_
                      | extend Meeting = tostring(parse_json(tostring(parse_json(tostring(RawEventData.ExchangeMetaData)).To))[0])
                      | extend PolicyName = tostring(parse_json(tostring(RawEventData.PolicyDetails))[0].PolicyName)
                      | extend RuleName = tostring(parse_json(tostring(parse_json(tostring(RawEventData.PolicyDetails))[0].Rules))[0].RuleName)
                      | extend SensitiveInformationTypeName = tostring(parse_json(tostring(parse_json(tostring(parse_json(tostring(parse_json(tostring(RawEventData.PolicyDetails))[0].Rules))[0].ConditionsMatched)).SensitiveInformation))[0].SensitiveInformationTypeName)
              | project meetid,Meeting,PolicyName,RuleName,SensitiveInformationTypeName,UserId_
              | join kind=inner
                  (    
                  CloudAppEvents
                  | where RawEventData.Operation == 'MeetingParticipantDetail'
                  | extend meetid = tostring(RawEventData.MeetingDetailId)
                  )
                  on meetid
              | extend UPN = tostring(parse_json(tostring(RawEventData.Attendees))[0].UPN)
              | extend RecipientType = tostring(parse_json(tostring(RawEventData.Attendees))[0].RecipientType)
              | where RecipientType startswith 'Guest'
              | project UPN,RecipientType,Meeting,PolicyName,RuleName,SensitiveInformationTypeName,UserId_);
              let channel =( 
              CloudAppEvents
              | where Application == 'Microsoft Teams'
              | where ActionType == 'DLPRuleMatch'
              | extend UserId_ = tostring(RawEventData.UserId)
              | extend TeamName = tolower(parse_json(tostring(parse_json(tostring(RawEventData.ExchangeMetaData)).To))[0])
              | extend PolicyName = tostring(parse_json(tostring(RawEventData.PolicyDetails))[0].PolicyName)
                      | extend RuleName = tostring(parse_json(tostring(parse_json(tostring(RawEventData.PolicyDetails))[0].Rules))[0].RuleName)
                      | extend SensitiveInformationTypeName = tostring(parse_json(tostring(parse_json(tostring(parse_json(tostring(parse_json(tostring(RawEventData.PolicyDetails))[0].Rules))[0].ConditionsMatched)).SensitiveInformation))[0].SensitiveInformationTypeName)
              | join kind=inner 
              (
              CloudAppEvents
              | where Application == 'Microsoft Teams'
              | extend TeamName = tolower(RawEventData.TeamName)
              | extend UPN = tostring(parse_json(tostring(RawEventData.Members))[0].UPN)
              | extend GroupId = tostring(RawEventData.AADGroupId)
              | extend HasGuestUsers = tostring(parse_json(tostring(RawEventData.ParticipantInfo)).HasGuestUsers)
              | extend HasUnauthenticatedUsers = tostring(parse_json(tostring(RawEventData.ParticipantInfo)).HasUnauthenticatedUsers)
              ) on TeamName
              | where HasGuestUsers == 'true' or HasUnauthenticatedUsers == 'true'
              | project TeamName,ActionType,HasGuestUsers,HasUnauthenticatedUsers,UPN,PolicyName,RuleName,SensitiveInformationTypeName,UserId_);
              let individual = (
              CloudAppEvents
              | where Application == 'Microsoft Teams'
              | where ActionType has 'DLPRuleMatch'
              | extend UPN = tostring(parse_json(tostring(parse_json(tostring(RawEventData.ExchangeMetaData)).To))[0])
              | where UPN matches regex '(\\S*@\\S*.\\S*)'
              | extend UserId_ = tostring(RawEventData.UserId)
              | extend TeamName = tolower(parse_json(tostring(parse_json(tostring(RawEventData.ExchangeMetaData)).To))[0])
              | extend PolicyName = tostring(parse_json(tostring(RawEventData.PolicyDetails))[0].PolicyName)
                      | extend RuleName = tostring(parse_json(tostring(parse_json(tostring(RawEventData.PolicyDetails))[0].Rules))[0].RuleName)
                      | extend SensitiveInformationTypeName = tostring(parse_json(tostring(parse_json(tostring(parse_json(tostring(parse_json(tostring(RawEventData.PolicyDetails))[0].Rules))[0].ConditionsMatched)).SensitiveInformation))[0].SensitiveInformationTypeName));
              let Account = (
                  union channel,TeamsMeeting,individual
                  | summarize count() by UserId_,SensitiveInformationTypeName
                  | extend Type = 'Account'
                  | take 25);
                      let Target = (
                  union channel,TeamsMeeting,individual
                  | extend Type = 'Target'
                  | where UPN <> ''
                  | summarize count() by UPN,Type,SensitiveInformationTypeName
                  | take 25);
                  let TopChannel = (
                  union channel,TeamsMeeting
                  | extend Type = 'TopChannel'
                  | where HasGuestUsers <> ''
                  | summarize count() by TeamName,Type,SensitiveInformationTypeName
                  | take 25);
                      let TopMeeting = (
                  union channel,TeamsMeeting
                  | extend Type = 'TopMeeting'
              | where RecipientType startswith 'Guest'
                  | summarize count() by Meeting,Type,SensitiveInformationTypeName
                  | take 25);
                  union Account,Target,TopChannel,TopMeeting

      - Name: DLPEndPointTuning
        DisplayName: Receive DLP tuning recommendations for Endpoints
        Description: This skill provides tuning recommendations for Endpoint DLP policies
        Settings:
          Target: Defender
          Template: |-
            let endpoint =(
            CloudAppEvents 
            | where RawEventData.Workload has 'EndPoint'
            | where RawEventData.PolicyMatchInfo <> ''
            | extend RuleName = tostring(parse_json(tostring(RawEventData.PolicyMatchInfo)).RuleName)
            | extend PolicyName = tostring(parse_json(tostring(RawEventData.PolicyMatchInfo)).PolicyName)
            | extend SensitiveInfoTypeName = tostring(parse_json(tostring(RawEventData.SensitiveInfoTypeData))[0].SensitiveInfoTypeName)
            | extend TargetDomain = tostring(RawEventData.TargetDomain)
            | extend EnforcementMode_ = tostring(parse_json(tostring(RawEventData.EndpointMetaData)).EnforcementMode)
            | extend EndpointOperation_ = tostring(parse_json(tostring(RawEventData.EndpointMetaData)).EndpointOperation)
            | extend document = tostring(RawEventData.ObjectId)
            | extend UserId = tostring(RawEventData.UserId)
            );
            let Account = (
              endpoint
                | summarize count() by UserId
                | extend Type = 'Account'
                | take 25);
            let Target = (
              endpoint
                | extend TargetDomain = tolower(RawEventData.TargetDomain)
                | where TargetDomain <> ''
                | extend Type = 'Target'
                | summarize count() by TargetDomain,Type,SensitiveInfoTypeName
                | take 25);
            let TargetPrinter = (
              endpoint
              | extend TargetPrinterName = tostring(RawEventData.TargetPrinterName)
              | where TargetPrinterName <> ''
                | extend Type = 'TargetPrinter'
                | summarize count() by TargetPrinterName,Type,SensitiveInfoTypeName
                | take 25);    
                let TargetFilePath = (
              endpoint
                | extend TargetFilePath = tostring(RawEventData.TargetFilePath)
                | extend Type = 'TargetFilePath'
                | where TargetFilePath <> ''
                | summarize count() by TargetFilePath,Type,SensitiveInfoTypeName
                | take 25);    
                let Device = (
                endpoint
                | extend DeviceName_ = tostring(RawEventData.DeviceName)
                | extend Type = 'TopDevice'
                | where DeviceName_ <> ''
                | summarize count() by DeviceName_,Type,SensitiveInfoTypeName
                | take 25);
                    let Topdocument = (
            endpoint
                | extend Type = 'TopDoc'
                | extend docname = parse_path(document).Filename 
                | where docname <> ''
                | summarize count() by tostring(docname),Type,SensitiveInfoTypeName
                | take 25);
                        let TopSIT = (
              endpoint
                | extend Type = 'TopSIT'
                | summarize count() by SensitiveInfoTypeName,Type
                | take 25);
                union Account,Topdocument,TopSIT,Target,TargetFilePath,TargetPrinter,Device

      - Name: DLPOCRTuning
        DisplayName: Receive DLP tuning recommendations for OCR
        Description: This skill provides tuning recommendations for OCR enabled DLP policies
        Settings:
          Target: Defender
          Template: |-
            let endpoint =(
            CloudAppEvents 
            | where RawEventData.Workload has 'EndPoint'
            | where RawEventData.PolicyMatchInfo.PolicyName <> ''
            | mv-expand Sensitive = RawEventData.SensitiveInfoTypeData
            | extend TargetDomain = tostring(RawEventData.TargetDomain)
            | extend EnforcementMode_ = tostring(parse_json(tostring(RawEventData.EndpointMetaData)).EnforcementMode)
            | extend EndpointOperation_ = tostring(parse_json(tostring(RawEventData.EndpointMetaData)).EndpointOperation)
            | extend Location = tostring(parse_path(tostring(RawEventData.ObjectId)).FileType)
            | where Location has_any ('JPEG', 'JPG', 'PNG', 'BMP', 'TIFF','PDF'));
                    let Exchange = (
            CloudAppEvents 
            | where ActionType has 'DLPRuleMatch' 
            | extend Type = 'To'
            | where RawEventData.Workload has 'Exchange' 
            | mv-expand PolicyDetails = RawEventData.PolicyDetails
            | mv-expand Rules = PolicyDetails.Rules
            | mv-expand Sensitive = Rules.ConditionsMatched.SensitiveInformation
            | extend Location = tolower(Sensitive.Location)
            | where Location has_any ('JPEG', 'JPG', 'PNG', 'BMP', 'TIFF','PDF'));
            let Teams = (
            CloudAppEvents 
            | where ActionType has 'DLPRuleMatch' 
            | extend Type = 'To'
            | where RawEventData.Workload has 'MicrosoftTeams'
            | mv-expand PolicyDetails = RawEventData.PolicyDetails
            | mv-expand Rules = PolicyDetails.Rules
            | mv-expand Sensitive = Rules.ConditionsMatched.SensitiveInformation
            | extend FileSize_ = tostring(parse_json(tostring(RawEventData.ExchangeMetaData)).FileSize)
            | where toint(FileSize_) > 50000);
            let spo = (
            CloudAppEvents 
            | where ActionType has 'DLPRuleMatch' 
            | where RawEventData.Workload has 'SharePoint' or RawEventData.Workload has 'OneDrive'
            | extend Location = tostring((parse_path(ObjectName)).Filename)
            | mv-expand PolicyDetails = RawEventData.PolicyDetails
            | mv-expand Rules = PolicyDetails.Rules
            | mv-expand Sensitive = Rules.ConditionsMatched.SensitiveInformation
            | where Sensitive != ''
            | where Location has_any ('JPEG', 'JPG', 'PNG', 'BMP', 'TIFF','PDF'));
            union Exchange,Teams,spo,endpoint
            | extend sit = (Sensitive.SensitiveInformationTypeName)
            | extend sit = iff(isempty(sit),Sensitive.SensitiveInfoTypeName,Sensitive.SensitiveInformationTypeName)
            | extend PolicyName = PolicyDetails.PolicyName 
            | extend PolicyName = iff(isempty(PolicyName),RawEventData.PolicyMatchInfo.PolicyName,Sensitive.SensitiveInformationTypeName)
            | summarize UserId = make_set(tostring(RawEventData.UserId)), Detections = make_list(tostring(sit)),count(), arg_max(Timestamp, *) by Timestamp, tostring(RawEventData.UserId),tostring(Sensitive.SensitiveInformationTypeName),Location
            | extend To = todynamic(parse_json(tostring(parse_json(tostring(RawEventData.ExchangeMetaData)).To))[0])
            | mv-expand To
            | extend user = split(To,'@')
            | project Timestamp, tostring(RawEventData.UserId),tostring(sit),Location,Subject=ObjectName,tostring(RawEventData.Workload),tostring(RawEventData.UserId),count_,user[1],PolicyName

      - Name: SensitiveSharePointOverSharing
        DisplayName: Oversharing events in SharePoint and OneDrive
        Description: This skill provides details about oversharing events in SharePoint and OneDrive
        Inputs:
          - Name: department
            Description: Specify the department for which we should return the oversharing events
            Required: false
          - Name: sitecollection
            Description: Specify the site collection for which we should return the oversharing events
            Required: false
        Settings:
          Target: Defender
          Template: |-
            let department = '{{department}}';
            let sitecollection = '{{sitecollection}}';
            let sharinglink = (
            CloudAppEvents 
            | where RawEventData.Workload == 'OneDrive' or RawEventData.Workload == 'SharePoint' 
            | where RawEventData.ObjectId has sitecollection 
            | extend Operation = tostring(RawEventData.Operation) 
            //Filter to a smaller set of operations, add additional operations as needed 
            | where Operation == 'AddedToSecureLink' 
                or Operation == 'SecureLinkCreated' 
                or Operation == 'SecureLinkUsed' 
                or Operation == 'SharingSet' 
                or ActionType == 'RemoveProtection' 
            | extend Sharinglink = tostring(RawEventData.TargetUserOrGroupName)
            | where Sharinglink matches regex 'SharingLinks.[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}.Organization\\w*.[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}' 
            | join kind= leftouter 
            (CloudAppEvents
            | where ActionType == 'GroupRemoved'
            | extend TargetUserOrGroupName_ = tostring(RawEventData.TargetUserOrGroupName)     
            | extend Sharinglink = tostring(parse_json(tostring(RawEventData.ModifiedProperties))[0].NewValue)
            )
            on Sharinglink
            |extend Type = 'SharingLink'
            );
            let group = (
            CloudAppEvents 
            | where RawEventData.Workload == 'OneDrive' or RawEventData.Workload == 'SharePoint' 
            | where RawEventData.ObjectId has sitecollection 
            | extend Operation = tostring(RawEventData.Operation) 
            //Filter to a smaller set of operations, add additional operations as needed 
            | where Operation == 'AddedToSecureLink' 
                or Operation == 'SecureLinkCreated' 
                or Operation == 'SecureLinkUsed' 
                or Operation == 'SharingSet' 
                or ActionType == 'RemoveProtection' 
            | extend Sharinglink = tostring(RawEventData.TargetUserOrGroupName)
            | where Sharinglink has 'Everyone'
            | join kind= leftouter 
            (CloudAppEvents
            | where ActionType == 'CompanyLinkRemoved' 
            | extend TargetUserOrGroupName_ = tostring(RawEventData.TargetUserOrGroupName)     
            )
            on ObjectId
            | extend Type = 'Group'
            );
            union sharinglink,group
            | extend UnshareOp = tostring(RawEventData1.Operation)
            | extend ShareTime_ = tostring(RawEventData.CreationTime)
            | extend UnshareTime = tostring(RawEventData1.CreationTime)
            | project Type,ObjectName,Sharinglink,ShareTime_,UnshareOp,UnshareTime,tostring(RawEventData.UserId)
            | join kind=leftouter
            (
            IdentityInfo
            | where Timestamp > ago(7d)
            | extend AccountUpn = tolower(AccountUpn)
            )
            on $left.RawEventData_UserId == $right.AccountUpn
            | where Department has department
            | summarize arg_max(Timestamp, *) by Type,ObjectName,Sharinglink,ShareTime_,UnshareOp,UnshareTime,RawEventData_UserId,Department,Country,City

      - Name: SensitiveGetExternalUploadsfromclients
        DisplayName: Get uploads to external websites from clients containing sensitive information
        Description: Fetches uploads to external websites from clients containing sensitive information
        Inputs:
          - Name: site
            Description: Specify the site for which the uploads are to be fetched
            Required: false
          - Name: user
            Description: Specify the user for which the uploads are to be fetched
            Required: false
          - Name: sitname 
            Description: Specify the sensitive information type for which the uploads are to be fetched
            Required: false
        Settings:
          Target: Defender
          Template: |-
            let site = '{{site}}';
            let user = '{{user}}';
            let sitvar = '{{sitname}}';
            CloudAppEvents 
            | where RawEventData.Workload has 'EndPoint'
            | where RawEventData.TargetDomain has site
            | where RawEventData.UserId has user
            | where ActionType has 'FileUploadedToCloud'
            | mv-expand Sensitive = RawEventData.SensitiveInfoTypeData
            | where Sensitive.SensitiveInfoTypeName has sitvar
            | extend TargetDomain = tostring(RawEventData.TargetDomain)
            | extend EnforcementMode_ = tostring(parse_json(tostring(RawEventData.EndpointMetaData)).EnforcementMode)
            | extend EndpointOperation_ = tostring(parse_json(tostring(RawEventData.EndpointMetaData)).EndpointOperation)
            | extend FileName = tostring(parse_path(tostring(RawEventData.ObjectId)).Filename)
            | summarize count() by TargetDomain, Datatype=tostring(Sensitive.SensitiveInfoTypeName)

      - Name: SensitiveGetInformationaboutfilesuploadedtospecificsite
        DisplayName: Get the actual file uploads to specific external websites from clients containing sensitive information
        Description: Fetches the actual files uploads to specific external websites from clients
        Inputs:
          - Name: site
            Description: Specify the site for which the uploads are to be fetched
            Required: true
          - Name: sitname 
            Description: Specify the sensitive information type for which the uploads are to be fetched
            Required: false
          - Name: document 
            Description: Specify the document for which the uploads are to be fetched
            Required: false  
        Settings:
          Target: Defender
          Template: |-
            let site = '{{site}}';
            let sitvar = '{{sitname}}';
            let document = '{{document}}';
            CloudAppEvents 
            | where RawEventData.Workload has 'EndPoint'
            | where RawEventData.TargetDomain has site
            | where ActionType has 'FileUploadedToCloud'
            | mv-expand Sensitive = RawEventData.SensitiveInfoTypeData
            | where Sensitive.SensitiveInfoTypeName has sitvar
            | extend TargetDomain = tostring(RawEventData.TargetDomain)
            | extend EnforcementMode_ = tostring(parse_json(tostring(RawEventData.EndpointMetaData)).EnforcementMode)
            | extend EndpointOperation_ = tostring(parse_json(tostring(RawEventData.EndpointMetaData)).EndpointOperation)
            | extend FileName = tostring(parse_path(tostring(RawEventData.ObjectId)).Filename)
            | where FileName has document
            | summarize count() by TargetDomain, Datatype=tostring(Sensitive.SensitiveInfoTypeName),FileName

      - Name: SensitiveFilesUserAccessed
        DisplayName: Get information about sensitive files a user has been accessing
        Description: Fetches information about sensitive files being accessed by users
        Inputs:
          - Name: user
            Description: Specify the user for which you want to get file access
            Required: true
          - Name: ISP
            Description: Filter the information for a specific ISP
            Required: false
          - Name: IPTag
            Description: Filter the information for a specific IPTag
            Required: false
        Settings:
          Target: Defender
          Template: |-
            let user = '{{user}}';
            let ispvar = '{{ISP}}';
            let iptagvar = '{{IPTag}}';
            let endpoint = (
            CloudAppEvents
              | where ISP has ispvar
              | extend IPTags = tostring(IPTags)
              | where IPTags has iptagvar    
            | where RawEventData.UserId has user
            | where parse_json(tostring(RawEventData.SensitiveInfoTypeData)) != ''
            | where parse_json(tostring(RawEventData.SensitiveInfoTypeData)) != '[]'
            | extend sit = parse_json(tostring(RawEventData.SensitiveInfoTypeData))
            | mv-expand sit
            | extend UserId = tolower(RawEventData.UserId)
            | extend TargetDomain = tostring(RawEventData.TargetDomain)
            | extend ObjectName = iff(isempty(ObjectName),tostring(RawEventData.ObjectId),ObjectName)
            | summarize count() by DataType=tostring(sit.SensitiveInfoTypeName),CountryCode,City,UserId,Document=ObjectName,Workload=tostring(RawEventData.Workload),TargetDomain,ISP,tostring(IPTags));
            let office = ( 
            CloudAppEvents
            | where ActionType has 'DLPRuleMatch'
            | where RawEventData.UserId has user
            | extend sit = parse_json(tostring(parse_json(tostring(parse_json(tostring(parse_json(tostring(RawEventData.PolicyDetails))[0].Rules))[0].ConditionsMatched)).SensitiveInformation))
            | where sit != ''
            | mv-expand sit
            | extend UserId = tolower(RawEventData.UserId)
            | extend sit_SensitiveInfoTypeName = tostring(sit.SensitiveInformationTypeName)
                        | join kind=inner
            (CloudAppEvents
                | where ActionType !has 'DLPRuleMatch'
                | where ISP has ispvar
                | extend IPTags = tostring(IPTags)
                | where IPTags has iptagvar  
                | project ISP, ObjectId,IPTags,ActionType
            ) on ObjectId
            | summarize count() by DataType=sit_SensitiveInfoTypeName,UserId,Document=ObjectName,Workload=tostring(RawEventData.Workload),ISP=ISP1,IPTags=tostring(IPTags1));
            union endpoint,office
            | project DataType,CountryCode,City,UserId,Document,Workload,TargetDomain,Count=count_,ISP,tostring(IPTags)

      - Name: SensitivefilesaccessedbyCompromisedusers
        DisplayName: Get sensitive documents that are accessed by compromised users
        Description: Fetches sensitive documents that are accessed by compromised users
        Inputs:
          - Name: user
            Description: Specify the user for which the sensitive content is to be fetched
            Required: false
          - Name: document
            Description: Specify the document to identify to map to possible compromised users
            Required: false
          - Name: ISP
            Description: Filter the information for a specific ISP
            Required: false
          - Name: IPTag
            Description: Filter the information for a specific IPTag
            Required: false  
        Settings:
          Target: Defender
          Template: |-
            let ispvar = '{{ISP}}';
            let iptagvar = '{{IPTag}}';
            let user = '{{user}}';
            let document = '{{document}}';
            let AlertEvidence = (AlertEvidence
                    | where Timestamp > ago(31d)
            //| where ProcessCommandLine ==''
            | extend upnsuffix = todynamic (AdditionalFields).UPNSuffix
            | extend upn1 = iff(isempty(todynamic (AdditionalFields).Recipient),todynamic (AdditionalFields).Upn,todynamic (AdditionalFields).Recipient)
            | extend user = parse_json(tostring(todynamic(AdditionalFields).Account))
            | extend upn2 = strcat(user.Name,'@',user.UPNSuffix)
            | extend upn3 = iff(isempty(user.Name),upn1,upn2)
            | extend upn4 = strcat(AccountName,'@',AccountDomain)
            | extend upn5 = strcat(AccountName,'@',upnsuffix)
            | extend upn6 = iff(isempty(upnsuffix),upn4,upn5)
            | extend upn = iff(isempty(upn3),upn6,upn3)
            | extend upn = tolower(upn)
            | distinct upn,ThreatFamily,Categories
            | extend d = bag_pack("ThreatFamily", ThreatFamily, "Categories", Categories)
            | summarize AttackDetail = make_list(strcat(d)) by upn);
            let endpoint = (
            AlertEvidence
            | where upn has tolower(user)
            | join kind=inner 
            (
            CloudAppEvents
            | where ISP has ispvar
            | extend IPTags = tostring(IPTags)
            | where IPTags has iptagvar 
            | where parse_json(tostring(RawEventData.SensitiveInfoTypeData)) != ''
            | where parse_json(tostring(RawEventData.SensitiveInfoTypeData)) != '[]'
            | extend sit = parse_json(tostring(RawEventData.SensitiveInfoTypeData))
            | mv-expand sit
            | extend UserId = tolower(RawEventData.UserId)
            | extend TargetDomain = tostring(RawEventData.TargetDomain)
            | extend ObjectName = iff(isempty(ObjectName),tostring(RawEventData.ObjectId),ObjectName)
            | where ObjectName has document
            | summarize count() by tostring(sit.SensitiveInfoTypeName),CountryCode,City,UserId,ObjectName,tostring(RawEventData.Workload),TargetDomain,ISP,tostring(IPTags)
            )
            on $left.upn == $right.UserId);
            let office = ( AlertEvidence
            | where upn has tolower(user)
            | join kind=inner 
            (
            CloudAppEvents
            | where ActionType has 'DLPRuleMatch'
            | extend sit = parse_json(tostring(parse_json(tostring(parse_json(tostring(parse_json(tostring(RawEventData.PolicyDetails))[0].Rules))[0].ConditionsMatched)).SensitiveInformation))
            | where sit != ''
            | mv-expand sit
            | extend UserId = tolower(RawEventData.UserId)
            | extend sit_SensitiveInfoTypeName = tostring(sit.SensitiveInformationTypeName)
            | where url_decode(ObjectName) has document
                                  | join kind=inner
            (CloudAppEvents
                | where ActionType !has 'DLPRuleMatch'
                | where ISP has ispvar
                | extend IPTags = tostring(IPTags)
                | where IPTags has iptagvar  
                | project ISP, ObjectId,IPTags,ActionType
            ) on ObjectId
            | summarize count() by DataType=sit_SensitiveInfoTypeName,UserId,Document=ObjectName,Workload=tostring(RawEventData.Workload),ISP=ISP1,IPTags=tostring(IPTags1))
            on $left.upn == $right.UserId);
            union endpoint,office
            | join kind=leftouter
            (
            IdentityInfo
            | where Timestamp > ago(7d)
            | extend AccountUpn = tolower(AccountUpn)
            )
            on $left.upn == $right.AccountUpn
            | summarize arg_max(Timestamp, *) by sit_SensitiveInfoTypeName,CountryCode,City,UserId,ObjectName,RawEventData_Workload,TargetDomain,tostring(AttackDetail)
            | summarize sum(count_) by DataType=sit_SensitiveInfoTypeName,CountryCode,City,UserId,upn,Department,Document=ObjectName,Workload=RawEventData_Workload,TargetDomain,AttackDetail=tostring(AttackDetail),ISP,tostring(IPTags)

      - Name: SensitiveEmailAccessactivitybyCVEorVendororNetwork
        DisplayName: Get the sensitive file activity based on CVE,Vendor,ISP or IPTags for Exchange, email content.
        Description: Fetches the sensitive email activity correlated with CVE or Vendor
        Inputs:
          - Name: CVE
            Description: The CVE to investigate across the file activity
            Required: false
          - Name: Vendor
            Description: The vendor to investigate across the file activity
            Required: false
          - Name: ISP
            Description: Filter the information for a specific ISP
            Required: false
          - Name: IPTag
            Description: Filter the information for a specific IPTag
            Required: false
          - Name: sit
            Description: Filter the information for a specific Sensitivity Information Type
            Required: false  
        Settings:
          Target: Defender
          Template: |-
            let cveid1 = '{{CVE}}';
            let vendor = '{{Vendor}}';
            let ispvar = '{{ISP}}';
            let iptagvar = '{{IPTag}}';
            let sitvar = '{{sit}}';
            CloudAppEvents
              | where Timestamp > ago(30d)
              | where tostring(RawEventData.Workload) == "Exchange" 
              | where ActionType == "DlpRuleMatch"
              | extend sit = parse_json(tostring(parse_json(tostring(parse_json(tostring(parse_json(tostring(RawEventData.PolicyDetails))[0].Rules))[0].ConditionsMatched)).SensitiveInformation))
              | where sit != ''
              | mv-expand sit 
              | where tostring(sit.SensitiveInformationTypeName) has sitvar
              | project InternetMessageId=ObjectId,sit,Subject = ObjectName
              | join kind=inner 
              (
              CloudAppEvents
              | where tostring(RawEventData.Operation) == "MailItemsAccessed"
              | where tolower(ISP) has tolower(ispvar)
              | extend IPtagsv = iff(isnull(IPTags),'NotSet',IPTags)
              | extend IPTags = tostring(IPTags)
              | where IPtagsv has iptagvar
              | mv-expand RawEventData.Folders
              | mv-expand FolderItem = RawEventData_Folders.FolderItems
              | extend InternetMessageId = tostring(FolderItem.InternetMessageId)
              | extend SensitivityLabel = tostring(FolderItem.Sensitivity)
              )
              on $left.InternetMessageId == $right.InternetMessageId
              | join kind=leftouter 
              (
              DeviceInfo
              | summarize by DeviceId,PublicIP,DeviceName
              )
              on $left.IPAddress == $right.PublicIP
              | summarize arg_max(Timestamp, *) by UserId = tolower(RawEventData.UserId),InternetMessageId,ISP,tostring(IPTags),DeviceId
              | join kind = leftouter 
              (     
              DeviceTvmSoftwareVulnerabilities
              | extend cveid1 = iff(isempty(cveid1),'NotSet',cveid1)
              | extend vendor = iff(isempty(vendor),'NotSet',vendor)
              | where CveId has cveid1 or SoftwareVendor has vendor
              )
              on DeviceId   
                | join kind=leftouter
              (
              IdentityInfo
              | where Timestamp > ago(7d)
              | extend AccountUpn = tolower(AccountUpn)
              )
              on $left.UserId == $right.AccountUpn
            | summarize count = count() by DataType=tostring(sit.SensitiveInformationTypeName),SensitivityLabel,DeviceName,Department,SoftwareName,SoftwareVersion,ISP,tostring(IPTags),CveId


      - Name: SensitiveEmailsaccessedbyusers
        DisplayName: Who accessed the emails containing sensitive information and from where
        Description: Fetches the sensitive information type,label user and the email accessed as well as ISP, Device information
        Inputs:
          - Name: user
            Description: Specify the user id for which the email access is to be fetched
            Required: false
          - Name: subject
            Description: Specify the subject for which the email access is to be fetched
            Required: false
          - Name: InternetMessageId
            Description: Specify the InternetMessageId for which the email access is to be fetched
            Required: false
        Settings:
          Target: Defender
          Template: |-
            let user = '{{user}}';
            let subject = '{{subject}}';
            let InternetMessageId = '{{InternetMessageId}}';
            CloudAppEvents
              | where tostring(RawEventData.Workload) == "Exchange" 
              | where ActionType == "DlpRuleMatch"
              | where tolower(RawEventData.UserId) has tolower(user)
              | where ObjectId has InternetMessageId
              | where tolower(ObjectName) has tolower(subject)
              | extend sit = parse_json(tostring(parse_json(tostring(parse_json(tostring(parse_json(tostring(RawEventData.PolicyDetails))[0].Rules))[0].ConditionsMatched)).SensitiveInformation))
              | where sit != ''
              | mv-expand sit 
              | project InternetMessageId=ObjectId,sit,Subject = ObjectName
              | join kind=inner 
              (
              CloudAppEvents
              | where tostring(RawEventData.Operation) == "MailItemsAccessed"
              | mv-expand RawEventData.Folders
              | mv-expand FolderItem = RawEventData_Folders.FolderItems
              | extend InternetMessageId = tostring(FolderItem.InternetMessageId)
              | extend SensitivityLabel = tostring(FolderItem.Sensitivity)
              )
              on $left.InternetMessageId == $right.InternetMessageId
              | join kind=leftouter 
              (
              DeviceInfo
              | summarize by DeviceId,PublicIP,DeviceName
              )
              on $left.IPAddress == $right.PublicIP
              | summarize arg_max(Timestamp, *) by UserId = tostring(RawEventData.UserId),InternetMessageId,ISP,tostring(IPTags),DeviceName
              | project AccountType,Subject,DataType=sit.SensitiveInformationTypeName,SensitivityLabel,MailboxOwnerUPN = tostring(RawEventData.MailboxOwnerUPN),UserId = tostring(RawEventData.UserId),ISP,IPTags,CountryCode,UserAgent,DeviceName

      - Name: DLPInformationaboutforwarding
        DisplayName: Was the email forwarded from the user's mailbox
        Description: Fetches the full information about a message including if the message was forwarded.
        Inputs:
          - Name: user
            Description: Specify the user for which the email forwarding information is to be fetched
            Required: false
          - Name: subject
            Description: Specify the subject for which the email forwarding information is to be fetched
            Required: false
          - Name: InternetMessageId
            Description: Specify the InternetMessageId for which the email forwarding information is to be fetched
            Required: false
        Settings:
          Target: Defender
          Template: |-
            let user = '{{user}}';
            let subject = '{{subject}}';
            let InternetMessageId = '{{InternetMessageId}}';
              CloudAppEvents
              | where RawEventData.Workload has 'Exchange'
              | where tolower(RawEventData.UserId) has tolower(user)
              | where ActionType has "DLPRuleMatch"
              | where ObjectId has InternetMessageId
              | join kind=inner
              (
              EmailEvents
              | where Subject has subject
              | where InternetMessageId has InternetMessageId
              | extend ObjectId = InternetMessageId
              )
              on ObjectId
              | summarize by Subject,RecipientEmailAddress,InternetMessageId

      - Name: SensitiveUnlabelledDocumentOperations
        DisplayName: Show unlabelled document operations across departments in contrast to labelled
        Description: Fetches the unlabelled document operations across departments in contrast to labelled
        Inputs:
          - Name: department 
            Description: Specify the department for which the unlabelled document operations are to be fetched
            Required: false
        Settings:
          Target: Defender
          Template: |-
            let department = '{{department}}';
            let content = (
            CloudAppEvents
                | where Timestamp > ago(30d)
                | where ActionType in ('FileCopiedToClipboard', 'FileCopiedToNetworkShare', 'FileCopiedToRemoteDesktopSession', 'FileCopiedToRemovableMedia', 'FilePrinted', 'FileSensitivityLabelApplied', 'FileUploadedToCloud','FileUploaded','SharingSet', 'FileRead','FileRenamed', 'MipLabel', 'SensitivityLabelApplied', 'SensitivityLabeledFileOpened', 'SensitivityLabelRemoved', 'SensitivityLabelUpdated', 'ArchiveCreated', 'FileAccessedByUnallowedApp', 'FileArchived','FileAccessed', 'FileCreatedOnNetworkShare', 'FileCreatedOnRemovableMedia', 'FileModified', 'RemoveProtection','FileTransferredByBluetooth', 'WebpagePrinted', 'WebpageCopiedToClipboard', 'WebpageSavedToLocal', 'PastedToBrowser')
                | where Application <> 'Microsoft Exchange Online'
                | extend ObjectId_ = tostring(RawEventData.ObjectId)
                | where ObjectId_ !has 'AppData'
                | where ActivityType <> 'Send'
                | extend LabelGUID1 = parse_json(tostring(RawEventData.SensitivityLabelEventData)).SensitivityLabelId
                | extend LabelGUID2 = iff(isempty(tostring(RawEventData.LabelId)), LabelGUID1, tostring(RawEventData.LabelId)) 
                | extend LabelGUID3 = iff(isempty(tostring(RawEventData.SensitivityLabelId)), LabelGUID2, tostring(RawEventData.SensitivityLabelId)) 
                | extend OldSensitivityLabelId = tostring(parse_json(tostring(RawEventData.SensitivityLabelEventData)).OldSensitivityLabelId)
                | extend LabelGUID = iff(isempty(tostring(LabelGUID3)),OldSensitivityLabelId, tostring(LabelGUID3))  
            | extend userid= tolower(RawEventData.UserId)
            );
            let unlabelledcontent = (
            content
            | where LabelGUID ==''
            |summarize count() by userid
            | extend Type = 'UnLabelledOps'
            );
            let labelledcontent=(
            content
            | where LabelGUID !=''
            | summarize count() by userid
            | extend Type = 'LabelledOps');
            union unlabelledcontent,labelledcontent
            | join kind=leftouter
            (
            IdentityInfo
            | where Timestamp > ago(7d)
            | extend AccountUpn = tolower(AccountUpn)
            )
            on $left.userid == $right.AccountUpn
            | where Department has department
            | summarize arg_max(Timestamp, *) by userid,Type
            | summarize sum(count_) by Department,Type

      - Name: SensitiveInformationOperationsbyDepartment
        DisplayName: Show Sensitive document operations across based on Sensitive Information Type, department and location
        Description: Fetches the sensitive document operations across based on Sensitive Information Type, department and location
        Inputs:
         - Name: department 
           Description: Specify the department for which the sensitive document operations are to be fetched
           Required: false
         - Name: sitname 
           Description: Specify the sensitive information type for which the sensitive document operations are to be fetched
           Required: false
        Settings:
          Target: Defender
          Template: |-
            let department = '{{department}}';
            let sitvar = '{{sitname}}';
              let endpoint = (
            CloudAppEvents
            | where parse_json(tostring(RawEventData.SensitiveInfoTypeData)) != ''
            | where parse_json(tostring(RawEventData.SensitiveInfoTypeData)) != '[]'
            | extend sit = parse_json(tostring(RawEventData.SensitiveInfoTypeData))
            | mv-expand sit
            | where sit.SensitiveInfoTypeName has sitvar
            | extend UserId = tolower(RawEventData.UserId)
            | extend TargetDomain = tostring(RawEventData.TargetDomain)
            | extend ObjectName = iff(isempty(ObjectName),tostring(RawEventData.ObjectId),ObjectName)
            | summarize count() by Datatype=tostring(sit.SensitiveInfoTypeName),CountryCode,City,UserId,ObjectName,tostring(RawEventData.Workload),TargetDomain);
            let office = (
            CloudAppEvents
            | where ActionType has 'DLPRuleMatch'
            | extend sit = parse_json(tostring(parse_json(tostring(parse_json(tostring(parse_json(tostring(RawEventData.PolicyDetails))[0].Rules))[0].ConditionsMatched)).SensitiveInformation))
            | where sit != ''
            | mv-expand sit
            | extend UserId = tolower(RawEventData.UserId)
            | extend sit_SensitiveInfoTypeName = tostring(sit.SensitiveInformationTypeName)
                | join kind=inner
                        (CloudAppEvents
                            | where ActionType !has 'DLPRuleMatch'
                            | project ISP, ObjectId,IPTags,ActionType,CountryCode,City
                            | where CountryCode != ''
                        ) on ObjectId
                        | extend CountryCode = CountryCode1
                        | extend City = City1
            | summarize count() by Datatype=sit_SensitiveInfoTypeName,UserId,ObjectName,tostring(RawEventData.Workload),CountryCode,City);
            union endpoint,office
            | join kind=inner
            (
            IdentityInfo
            | where Timestamp > ago(7d)
            | extend AccountUpn = tolower(AccountUpn)
            )
            on $left.UserId == $right.AccountUpn
            | where Department has department
            | summarize arg_max(Timestamp, *) by Datatype,CountryCode,City
            | summarize sum(count_) by Datatype,CountryCode,City,Department

      - Name: SensitiveLabelledActivitybyCVEorVendor
        DisplayName: Get the sensitivity label file activity based on CVE or Vendor
        Description: Fetches the sensitivity label file activity happening on the Device associated with the CVE or Vendor
        Inputs:
          - Name: CVE
            Description: The CVE to investigate across the file activity
            Required: false
          - Name: Vendor
            Description: The vendor to investigate across the file activity
            Required: false
          - Name: ISP
            Description: Filter the information for a specific ISP
            Required: false
          - Name: IPTag
            Description: Filter the information for a specific IPTag
            Required: false
        Settings:
          Target: Defender
          Template: |-
            let cveid1 = '{{CVE}}';
            let vendor = '{{Vendor}}';
            let ispvar = '{{ISP}}';
            let iptagvar = '{{IPTag}}';
                CloudAppEvents
                  | where RawEventData.MDATPDeviceId != ''
                  | where ISP has ispvar
                  | extend IPTags = tostring(IPTags)
                  | where IPTags has iptagvar
                  | where Timestamp > ago(31d)
                  | where ActionType in ('FileCopiedToClipboard', 'FileCopiedToNetworkShare', 'FileCopiedToRemoteDesktopSession', 'FileCopiedToRemovableMedia', 'FilePrinted', 'FileSensitivityLabelApplied', 'FileUploadedToCloud','FileUploaded','SharingSet', 'FileRead','FileRenamed', 'MipLabel', 'SensitivityLabelApplied', 'SensitivityLabeledFileOpened', 'SensitivityLabelRemoved', 'SensitivityLabelUpdated', 'ArchiveCreated', 'FileAccessedByUnallowedApp', 'FileArchived','FileAccessed', 'FileCreatedOnNetworkShare', 'FileCreatedOnRemovableMedia', 'FileModified', 'RemoveProtection','FileTransferredByBluetooth', 'WebpagePrinted', 'WebpageCopiedToClipboard', 'WebpageSavedToLocal', 'PastedToBrowser','FileSensitivityLabelChanged','FileDownloaded','SensitivityLabelPolicyMatched','SharingLinkCreated','SharingLinkUsed')
                  | where Application <> 'Microsoft Exchange Online'
                  | extend ObjectId_ = tostring(RawEventData.ObjectId)
                  | where ObjectId_ !has 'AppData'
                  | where ActivityType <> 'Send'
                  | extend LabelGUID1 = parse_json(tostring(RawEventData.SensitivityLabelEventData)).SensitivityLabelId
                  | extend LabelGUID2 = iff(isempty(tostring(RawEventData.LabelId)), LabelGUID1, tostring(RawEventData.LabelId)) 
                  | extend LabelGUID3 = iff(isempty(tostring(RawEventData.SensitivityLabelId)), LabelGUID2, tostring(RawEventData.SensitivityLabelId)) 
                  | extend OldSensitivityLabelId = tostring(parse_json(tostring(RawEventData.SensitivityLabelEventData)).OldSensitivityLabelId)
                  | extend LabelGUID = iff(isempty(tostring(LabelGUID3)),OldSensitivityLabelId, tostring(LabelGUID3))  
                  | where LabelGUID !=''
                  | extend userid = tolower(RawEventData.UserId)
                  | extend DeviceId = tostring(RawEventData.MDATPDeviceId)
                  | extend AppUsed = tostring(RawEventData.Application)
                  | join kind = inner
                  (
                  DeviceTvmSoftwareVulnerabilities
                  | extend cveid1 = iff(isempty(cveid1),'NotSet',cveid1)
                  | extend vendor = iff(isempty(vendor),'NotSet',vendor)
                  | where CveId has cveid1 or SoftwareVendor has vendor
                  )
              on DeviceId
              | summarize count() by LabelGUID,City,userid,CountryCode,ISP,tostring(IPTags),DeviceName,AppUsed
              | join kind=leftouter
              (
              IdentityInfo
              | where Timestamp > ago(7d)
              | extend AccountUpn = tolower(AccountUpn)
              )
              on $left.userid == $right.AccountUpn
              | summarize arg_max(Timestamp, *) by LabelGUID,Department,Country,userid,City,DeviceName,ISP,AppUsed,tostring(IPTags)
              | summarize sum(count_) by LabelGUID,Department,City,CountryCode,userid,ISP,tostring(IPTags),DeviceName,AppUsed

      - Name: SensitiveLabelledActivityoutliers
        DisplayName: Get the sensitivity label file activity that are outliers or anomalies
        Description: Fetches the sensitivity label file activity happening and identifies the outliers and anomalies
        Inputs:
          - Name: ISP
            Description: Filter the information for a specific ISP
            Required: false
          - Name: IPTag
            Description: Filter the information for a specific IPTag
            Required: false
        Settings:
          Target: Defender
          Template: |-
            let ispvar = '{{ISP}}';
            let iptagvar = '{{IPTag}}';
               CloudAppEvents
                  | where Timestamp > ago(14d)
                  | where RawEventData.MDATPDeviceId != ''
                  | where ISP has ispvar
                  | extend IPTags = tostring(IPTags)
                  | where IPTags has iptagvar
                  | where ActionType in ('FileCopiedToClipboard', 'FileCopiedToNetworkShare', 'FileCopiedToRemoteDesktopSession', 'FileCopiedToRemovableMedia', 'FilePrinted', 'FileSensitivityLabelApplied', 'FileUploadedToCloud','FileUploaded','SharingSet', 'FileRead','FileRenamed', 'MipLabel', 'SensitivityLabelApplied', 'SensitivityLabeledFileOpened', 'SensitivityLabelRemoved', 'SensitivityLabelUpdated', 'ArchiveCreated', 'FileAccessedByUnallowedApp', 'FileArchived','FileAccessed', 'FileCreatedOnNetworkShare', 'FileCreatedOnRemovableMedia', 'FileModified', 'RemoveProtection','FileTransferredByBluetooth', 'WebpagePrinted', 'WebpageCopiedToClipboard', 'WebpageSavedToLocal', 'PastedToBrowser','FileSensitivityLabelChanged','FileDownloaded','SensitivityLabelPolicyMatched','SharingLinkCreated','SharingLinkUsed')
                  | where Application <> 'Microsoft Exchange Online'
                  | extend ObjectId_ = tostring(RawEventData.ObjectId)
                  | where ObjectId_ !has 'AppData'
                  | where ActivityType <> 'Send'
                  | extend LabelGUID1 = parse_json(tostring(RawEventData.SensitivityLabelEventData)).SensitivityLabelId
                  | extend LabelGUID2 = iff(isempty(tostring(RawEventData.LabelId)), LabelGUID1, tostring(RawEventData.LabelId)) 
                  | extend LabelGUID3 = iff(isempty(tostring(RawEventData.SensitivityLabelId)), LabelGUID2, tostring(RawEventData.SensitivityLabelId)) 
                  | extend OldSensitivityLabelId = tostring(parse_json(tostring(RawEventData.SensitivityLabelEventData)).OldSensitivityLabelId)
                  | extend LabelGUID = iff(isempty(tostring(LabelGUID3)),OldSensitivityLabelId, tostring(LabelGUID3))  
                  | where LabelGUID !=''
                  | extend userid = tolower(RawEventData.UserId)
                  | extend DeviceId = tostring(RawEventData.MDATPDeviceId)
                  | extend AppUsed = tostring(RawEventData.Application)
            | summarize EventCount=count() by userid,LabelGUID,ISP,tostring(IPTags),AppUsed, bin(Timestamp,30m)
            | order by Timestamp
            | summarize EventCount=make_list(EventCount),TimeGenerated=make_list(Timestamp) by userid,ISP,tostring(IPTags),AppUsed
            | extend outliers=series_decompose_anomalies(EventCount)
            | mv-expand TimeGenerated, EventCount, outliers
            | where outliers == 1
            | summarize aggregate=sum(todecimal(EventCount)) by userid,ISP,tostring(IPTags),AppUsed

      - Name: SensitiveEndpointactivitybyCVEorVendor
        DisplayName: Get the sensitive file activity based on CVE or Vendor
        Description: Fetches the sensitive file activity happening on the Device associated with the CVE or Vendor
        Inputs:
          - Name: CVE
            Description: The CVE to investigate across the file activity
            Required: false
          - Name: Vendor
            Description: The vendor to investigate across the file activity
            Required: false
          - Name: ISP
            Description: Filter the information for a specific ISP
            Required: false
          - Name: IPTag
            Description: Filter the information for a specific IPTag
            Required: false
          - Name: sit
            Description: Filter the information for a specific Sensitivity Information Type
            Required: false  
        Settings:
          Target: Defender
          Template: |-
            let cveid = '{{CVE}}';
            let vendor = '{{Vendor}}';
            let ispvar = '{{ISP}}';
            let iptagvar = '{{IPTag}}';
            let sitvar = '{{sit}}';
              DeviceTvmSoftwareVulnerabilities 
              | where CveId has cveid
              | where SoftwareVendor has vendor
              | join kind = inner
              (
                CloudAppEvents 
              | where ISP has ispvar
              | extend IPTags = tostring(IPTags)
              | where IPTags has iptagvar  
              | where parse_json(tostring(RawEventData.SensitiveInfoTypeData)) != "" 
              | where parse_json(tostring(RawEventData.SensitiveInfoTypeData)) != "[]" 
              | extend sit = parse_json(tostring(RawEventData.SensitiveInfoTypeData)) 
              | mv-expand sit 
              | extend UserId = tolower(RawEventData.UserId) 
              | extend SensitiveInfoTypeName = tostring(sit.SensitiveInfoTypeName)
              | where SensitiveInfoTypeName has sitvar  
              | extend document = tostring(RawEventData.ObjectId) 
              | extend DeviceId = tostring(RawEventData.MDATPDeviceId)
              | extend AppUsed = tostring(RawEventData.Application)
              ) on DeviceId
              | summarize count = count() by SensitiveInfoTypeName,DeviceName,CountryCode,SoftwareName,SoftwareVersion,AppUsed,ISP,tostring(IPTags) 


      - Name: SensitiveEndpointactivitybyNetwork
        DisplayName: Get the sensitive file activity based on network ISP or IPTags
        Description: Fetches the sensitive file activity happening on the Device associated with the network ISP or IPTags
        Inputs:
          - Name: Vendor
            Description: The vendor to investigate across the file activity
            Required: false
          - Name: ISP
            Description: Filter the information for a specific ISP
            Required: false
          - Name: IPTag
            Description: Filter the information for a specific IPTag
            Required: false
          - Name: sit
            Description: Filter the information for a specific Sensitivity Information Type
            Required: false  
        Settings:
          Target: Defender
          Template: |-
            let vendor = '{{Vendor}}';
            let ispvar = '{{ISP}}';
            let iptagvar = '{{IPTag}}';
            let sitvar = '{{sit}}';
                CloudAppEvents 
              | where ISP has ispvar
              | extend IPTags = tostring(IPTags)
              | where IPTags has iptagvar  
              | where parse_json(tostring(RawEventData.SensitiveInfoTypeData)) != "" 
              | where parse_json(tostring(RawEventData.SensitiveInfoTypeData)) != "[]" 
              | extend sit = parse_json(tostring(RawEventData.SensitiveInfoTypeData)) 
              | mv-expand sit 
              | extend UserId = tolower(RawEventData.UserId) 
              | extend SensitiveInfoTypeName = tostring(sit.SensitiveInfoTypeName)
              | where SensitiveInfoTypeName has sitvar  
              | extend document = tostring(RawEventData.ObjectId) 
              | extend DeviceId = tostring(RawEventData.MDATPDeviceId)
              | extend AppUsed = tostring(RawEventData.Application)
              | summarize count = count() by SensitiveInfoTypeName,CountryCode,AppUsed,ISP,tostring(IPTags),DeviceId 

      - Name: SensitiveContentAnomalies
        DisplayName: Get Sensitive content anomalies from the log stream
        Description: Fetches the Sensitive content anomalies from the log stream
        Inputs:
          - Name: ISP
            Description: Filter the information for a specific ISP
            Required: false
          - Name: IPTag
            Description: Filter the information for a specific IPTag
            Required: false
        Settings:
          Target: Defender
          Template: |-
            let ispvar = '{{ISP}}';
            let iptagvar = '{{IPTag}}';
            let min_peak_t=now(-30d);
            let max_peak_t=now(-14d);
            let min_baseline_t=now(-13d);
            let max_baseline_t=now(-1d);
            let splitime=(max_baseline_t+min_peak_t)/2.0;
            CloudAppEvents
              | where ISP has ispvar
              | extend IPTags = tostring(IPTags)
              | where IPTags has iptagvar
              | where parse_json(tostring(RawEventData.SensitiveInfoTypeData)) != ""
              | where parse_json(tostring(RawEventData.SensitiveInfoTypeData)) != "[]"
              | extend sit = parse_json(tostring(RawEventData.SensitiveInfoTypeData))
            | mv-expand sit
            | extend SensitiveInfoTypeName = tostring(sit.SensitiveInfoTypeName)
            | extend UserId = tostring(RawEventData.UserId)
            | extend document = tostring(RawEventData.ObjectId)
            | project Timestamp,document,UserId,SensitiveInfoTypeName,DeviceType,ISP,IPTags
            | where (Timestamp    between(min_baseline_t..max_baseline_t)) or
                    (Timestamp   between(min_peak_t..max_peak_t))
            | extend AB=iff(Timestamp > splitime, 'Anomaly', 'Baseline')
            | evaluate diffpatterns(AB, 'Anomaly', 'Baseline')


      - Name: SensitiveEndpointinternetfacing
        DisplayName: Get the sensitive file activity for devices that are internet facing
        Description: Fetches the sensitive file activity happening on the Devices that are internet facing
        Inputs:
          - Name: sit
            Description: Filter the information for a specific Sensitivity Information Type
            Required: false  
        Settings:
          Target: Defender
          Template: |-
            let sitvar = '{{sit}}';
              DeviceInfo
              | where Timestamp > ago(7d)
              | where IsInternetFacing
              | extend InternetFacingInfo = AdditionalFields
              | extend InternetFacingReason = extractjson("$.InternetFacingReason", InternetFacingInfo, typeof(string)), InternetFacingLocalPort = extractjson("$.InternetFacingLocalPort", InternetFacingInfo, typeof(int)), InternetFacingScannedPublicPort = extractjson("$.InternetFacingPublicScannedPort", InternetFacingInfo, typeof(int)), InternetFacingScannedPublicIp = extractjson("$.InternetFacingPublicScannedIp", InternetFacingInfo, typeof(string)), InternetFacingLocalIp = extractjson("$.InternetFacingLocalIp", InternetFacingInfo, typeof(string)),   InternetFacingTransportProtocol=extractjson("$.InternetFacingTransportProtocol", InternetFacingInfo, typeof(string)), InternetFacingLastSeen = extractjson("$.InternetFacingLastSeen", InternetFacingInfo, typeof(datetime))
              | summarize arg_max(Timestamp, *) by DeviceId
              | project DeviceId,InternetFacingInfo,DeviceName
              | join kind = inner
              (
                CloudAppEvents 
              | where Timestamp > ago(31d)
              | where parse_json(tostring(RawEventData.SensitiveInfoTypeData)) != "" 
              | where parse_json(tostring(RawEventData.SensitiveInfoTypeData)) != "[]" 
              | extend sit = parse_json(tostring(RawEventData.SensitiveInfoTypeData)) 
              | mv-expand sit 
              | extend UserId = tolower(RawEventData.UserId) 
              | extend SensitiveInfoTypeName = tostring(sit.SensitiveInfoTypeName)
              | where SensitiveInfoTypeName has sitvar  
              | extend document = tostring(RawEventData.ObjectId) 
              | extend DeviceId = tostring(RawEventData.MDATPDeviceId)
              | extend AppUsed = tostring(RawEventData.Application)
              ) on DeviceId
              | summarize count = count() by SensitiveInfoTypeName,DeviceName,CountryCode,InternetFacingInfo,AppUsed

      - Name: SensitiveContentSummaryofApplications
        DisplayName: Get Applications that are accessing sensitive content
        Description: Fetches the Applications that are accessing sensitive content
        Settings:
          Target: Defender
          Template: |-
            CloudAppEvents 
                            | where parse_json(tostring(RawEventData.SensitiveInfoTypeData)) != "" 
                            | where parse_json(tostring(RawEventData.SensitiveInfoTypeData)) != "[]" 
                            | extend sit = parse_json(tostring(RawEventData.SensitiveInfoTypeData)) 
                            | mv-expand sit 
                            | extend UserId = tolower(RawEventData.UserId) 
                            | extend SensitiveInfoTypeName = tostring(sit.SensitiveInfoTypeName)
                            | extend document = tostring(RawEventData.ObjectId) 
                            | extend DeviceId = tostring(RawEventData.MDATPDeviceId)
                            | extend AppUsed = tolower(RawEventData.Application)
                            | where AppUsed !=""
                            | summarize by AppUsed,DeviceId,SensitiveInfoTypeName
                            | join kind=inner 
                            (
                            DeviceProcessEvents
                            | where Timestamp > ago(7d)
                            | extend AppUsed = tolower(FileName)
                            | summarize by AppUsed,SHA256,ProcessVersionInfoCompanyName,ProcessVersionInfoProductName,DeviceId
                            )
                            on AppUsed,DeviceId
                            | summarize count() by AppUsed,SHA256,ProcessVersionInfoCompanyName,ProcessVersionInfoProductName
                            | sort by count_

      - Name: SensitiveContentApplicationdetail
        DisplayName: Get the Sensitive data types that an Application is accessing
        Description: Fetches the Sensitive data types that and Application is accessing
        Inputs:
          - Name: ApplicationName
            Description: Filter the information for a specific Application
            Required: true          
          - Name: SensitiveInfoTypeName
            Description: Filter the information for a specific Sensitive Information Type
            Required: false
        Settings:
          Target: Defender
          Template: |-
              let sitvar = '{{SensitiveInfoTypeName}}';
              let app = '{{ApplicationName}}';
                CloudAppEvents 
                            | where parse_json(tostring(RawEventData.SensitiveInfoTypeData)) != "" 
                            | where parse_json(tostring(RawEventData.SensitiveInfoTypeData)) != "[]" 
                            | extend sit = parse_json(tostring(RawEventData.SensitiveInfoTypeData)) 
                            | mv-expand sit 
                            | extend UserId = tolower(RawEventData.UserId) 
                            | extend SensitiveInfoTypeName = tostring(sit.SensitiveInfoTypeName)
                            | where SensitiveInfoTypeName has sitvar  
                            | extend document = tostring(RawEventData.ObjectId) 
                            | extend DeviceId = tostring(RawEventData.MDATPDeviceId)
                            | extend AppUsed = tolower(RawEventData.Application)
                            | where AppUsed !=""
                            | where AppUsed has tolower(app)
                            | summarize by AppUsed,DeviceId,SensitiveInfoTypeName
                            | join kind=inner 
                            (
                            DeviceProcessEvents
                            | where Timestamp > ago(7d)
                            | extend AppUsed = tolower(FileName)
                            | summarize by AppUsed,SHA256,ProcessVersionInfoCompanyName,ProcessVersionInfoProductName,DeviceId
                            )
                            on AppUsed,DeviceId
                            | summarize count() by AppUsed,SHA256,ProcessVersionInfoCompanyName,ProcessVersionInfoProductName,SensitiveInfoTypeName
                            | sort by count_

      - Name: SensitiveContentAppNetworkActivity
        DisplayName: Get Application network activity for apps accessing sensitive content
        Description: Fetches the Application network activity for apps accessing sensitive content
        Inputs:
          - Name: ApplicationName
            Description: Filter the information for a specific Application
            Required: true          
          - Name: SensitiveInfoTypeName
            Description: Filter the information for a specific Sensitive Information Type
            Required: false
        Settings:
          Target: Defender
          Template: |-
            let sitvar = '{{SensitiveInfoTypeName}}';
            let app = '{{ApplicationName}}';
              let corequery = (
              CloudAppEvents 
                            | where parse_json(tostring(RawEventData.SensitiveInfoTypeData)) != "" 
                            | where parse_json(tostring(RawEventData.SensitiveInfoTypeData)) != "[]" 
                            | extend sit = parse_json(tostring(RawEventData.SensitiveInfoTypeData)) 
                            | mv-expand sit 
                            | extend UserId = tolower(RawEventData.UserId) 
                            | extend SensitiveInfoTypeName = tostring(sit.SensitiveInfoTypeName)
                            | where SensitiveInfoTypeName has sitvar  
                            | extend document = tostring(RawEventData.ObjectId) 
                            | extend DeviceId = tostring(RawEventData.MDATPDeviceId)
                            | extend AppUsed = tolower(RawEventData.Application)
                            | where AppUsed == tolower(app)
                            | where AppUsed !=""
                            | summarize count() by AppUsed,SensitiveInfoTypeName,DeviceId
                            | join kind=inner (
                            DeviceNetworkEvents
                            | extend AppUsed = tolower(InitiatingProcessFileName))
                            on AppUsed,DeviceId);
                corequery
                | summarize count() by DeviceId,AppUsed,SensitiveInfoTypeName,RemotePort,RemoteUrl,RemoteIP,LocalIPType,RemoteIPType,DeviceName,InitiatingProcessSHA256

      - Name: Getemailbyrecipient
        DisplayName: Get email messages by recipient
        Description: Fetches the email messages by recipient
        Inputs:
          - Name: Recipient
            Description: Filter the information for a specific Recipient
            Required: true   
        Settings:
          Target: Defender
          Template: |-
              let Recipient = '{{Recipient}}';
              EmailEvents
              | where RecipientEmailAddress has Recipient
              | project SenderMailFromAddress,Subject,RecipientEmailAddress,AttachmentCount,UrlCount,InternetMessageId

      - Name: MicrosoftCopilotActivityRiskyUser
        DisplayName: Get the Microsoft Copilot activity labelled and unlabelled as well as data type activity for Risky Users
        Description: Fetches the Microsoft Copilot activity labelled and unlabelled as well as data type activity for Risky Users
        Settings:
          Target: Defender
          Template: |-
            CloudAppEvents
              | where Timestamp > ago(30d)
              | where ActionType has 'CopilotInteraction'
              | extend AccessedResources = iif(array_length(RawEventData.CopilotEventData.AccessedResources)==0, todynamic('Empty:Field') , RawEventData.CopilotEventData.AccessedResources)
              | mv-expand AccessedResources
              | extend Content = url_decode(tostring(AccessedResources.SiteUrl))
              | extend ObjectName = tolower(replace_string(Content,'?web=1',''))
              | extend UserId = tostring(RawEventData.UserId)
              | extend LabelGUID = tostring(AccessedResources.SensitivityLabelId)
              | summarize arg_max(Timestamp, *) by UserId,ObjectName
              | join kind=leftouter 
              (CloudAppEvents
              | where ActionType has 'DLPRuleMatch'
              | extend sit = parse_json(tostring(parse_json(tostring(parse_json(tostring(parse_json(tostring(RawEventData.PolicyDetails))[0].Rules))[0].ConditionsMatched)).SensitiveInformation))
              | where sit != ''
              | mv-expand sit
              | extend UserId = tolower(RawEventData.UserId)
              | extend ObjectName = tolower(url_decode(tostring(ObjectName)))
              | where ObjectName != ''
              | extend sit_SensitiveInfoTypeName = tostring(sit.SensitiveInformationTypeName)
              | summarize by sit_SensitiveInfoTypeName,ObjectName
                | summarize SensitiveInformationTypes = make_list(strcat(sit_SensitiveInfoTypeName)) by ObjectName)
              on ObjectName
              | extend AISystemPlugin_ = tostring(parse_json(tostring(parse_json(tostring(RawEventData.CopilotEventData)).AISystemPlugin)))
              | extend ModelName_ = tostring(parse_json(tostring(parse_json(tostring(RawEventData.CopilotEventData)).ModelTransparencyDetails))[0].ModelName)
                | extend Id_ = tostring(RawEventData.Id)
                | summarize AccessedSite = make_list(strcat(ObjectName)) by UserId,Id_,LabelGUID,tostring(SensitiveInformationTypes),City,CountryCode
              | extend upn = tolower(UserId)
              | join kind=inner 
              ( AlertEvidence
                      | where Timestamp > ago(31d)
              | where ProcessCommandLine ==''
              | extend upnsuffix = todynamic (AdditionalFields).UPNSuffix
              | extend upn1 = iff(isempty(todynamic (AdditionalFields).Recipient),todynamic (AdditionalFields).Upn,todynamic (AdditionalFields).Recipient)
              | extend user = parse_json(tostring(todynamic(AdditionalFields).Account))
              | extend upn2 = strcat(user.Name,'@',user.UPNSuffix)
              | extend upn3 = iff(isempty(user.Name),upn1,upn2)
              | extend upn4 = strcat(AccountName,'@',AccountDomain)
              | extend upn5 = strcat(AccountName,'@',upnsuffix)
              | extend upn6 = iff(isempty(upnsuffix),upn4,upn5)
              | extend upn = iff(isempty(upn3),upn6,upn3)
              | extend upn = tolower(upn)
              | extend Type = 'Compromised'
              | summarize by  upn,AttackTitle=Title
              ) on upn
              | join kind=leftouter
              (
              IdentityInfo
              | where Timestamp > ago(7d)
              | extend AccountUpn = tolower(AccountUpn)
              | summarize arg_max(Timestamp, *) by AccountUpn
              )
              on $left.UserId == $right.AccountUpn
              | summarize by tostring(AccessedSite),LabelGUID,UserId,AttackTitle,DataType=tostring(SensitiveInformationTypes),Department,Manager


      - Name: MicrosoftCopilotActivityperlocation
        DisplayName: Get the Microsoft Copilot activity labelled and unlabelled as well as data type based on user location and department
        Description: Fetches the Microsoft Copilot activity labelled and unlabelled as well as data type based on user location and department
        Inputs:
          - Name: Department
            Description: Filter the information for a specific Department
            Required: false          
          - Name: LabelGUID
            Description: Filter the information for a specific LabelGUID
            Required: false
        Settings:
          Target: Defender
          Template: |-
            let departmentvar = '{{Department}}';
            let LabelGUIDvar = '{{LabelGUID}}';
              CloudAppEvents
              | where Timestamp > ago(30d)
              | where ActionType has 'CopilotInteraction'
              | extend AccessedResources = iif(array_length(RawEventData.CopilotEventData.AccessedResources)==0, todynamic('Empty:Field') , RawEventData.CopilotEventData.AccessedResources)
              | mv-expand AccessedResources
              | extend Content = url_decode(tostring(AccessedResources.SiteUrl))
              | extend ObjectName = tolower(replace_string(Content,'?web=1',''))
              | extend UserId = tostring(RawEventData.UserId)
              | extend LabelGUID = tostring(AccessedResources.SensitivityLabelId)
              | where LabelGUID == LabelGUIDvar
              | extend App = tostring(RawEventData.CopilotEventData.AppHost)
              | summarize arg_max(Timestamp, *) by UserId,ObjectName,App
              | join kind=leftouter 
              (CloudAppEvents
              | where ActionType has 'DLPRuleMatch'
              | extend sit = parse_json(tostring(parse_json(tostring(parse_json(tostring(parse_json(tostring(RawEventData.PolicyDetails))[0].Rules))[0].ConditionsMatched)).SensitiveInformation))
              | where sit != ''
              | mv-expand sit
              | extend UserId = tolower(RawEventData.UserId)
              | extend ObjectName = tolower(url_decode(tostring(ObjectName)))
              | where ObjectName != ''
              | extend sit_SensitiveInfoTypeName = tostring(sit.SensitiveInformationTypeName)
              | summarize by sit_SensitiveInfoTypeName,ObjectName
                | summarize SensitiveInformationTypes = make_list(strcat(sit_SensitiveInfoTypeName)) by ObjectName)
              on ObjectName
              | extend AISystemPlugin_ = tostring(parse_json(tostring(parse_json(tostring(RawEventData.CopilotEventData)).AISystemPlugin)))
              | extend ModelName_ = tostring(parse_json(tostring(parse_json(tostring(RawEventData.CopilotEventData)).ModelTransparencyDetails))[0].ModelName)
                | extend Id_ = tostring(RawEventData.Id)
                | summarize AccessedSite = make_list(strcat(ObjectName)) by UserId,Id_,LabelGUID,tostring(SensitiveInformationTypes),City,CountryCode,App
              | join kind=leftouter
              (
              IdentityInfo
              | where Timestamp > ago(7d)
              | extend AccountUpn = tolower(AccountUpn)
              | summarize arg_max(Timestamp, *) by AccountUpn
              )
              on $left.UserId == $right.AccountUpn
              | where Department has departmentvar
              | summarize by AccessedSites=tostring(AccessedSite),RequestId=Id_,App,LabelGUID,tostring(SensitiveInformationTypes),City,CountryCode,Department,JobTitle,Manager,BlastRadius,RiskLevel,RiskLevelDetails

      - Name: TopUsersByDLPEvidence
        DisplayName: Get Top Users with Data Loss Prevention Alerts
        Description: Identifies the top users based on the number of Microsoft Data Loss Prevention alerts and provides a breakdown of alert severity (high, medium, or low) for the last 7 days.
        Settings:
          Target: Defender
          Template: |-
            let timeframe = 7d;
            AlertEvidence
            | where TimeGenerated > ago(timeframe)
            | where DetectionSource == "Microsoft Data Loss Prevention"
            | extend AF = todynamic(AdditionalFields)
            // Don't parse Tags yet, just get basic user info first
            | extend User = case(
              isnotempty(AccountUpn), AccountUpn,
              isnotempty(AF.Name) and AF.Type =~ "account", tostring(AF.Name),
              ""
            )
            | where isnotempty(User)
            | summarize TotalAlerts = count() by User
            | top 5 by TotalAlerts
            | join kind=inner (
              AlertEvidence
              | where TimeGenerated > ago(timeframe) 
              | where DetectionSource == "Microsoft Data Loss Prevention"
              | extend AF = todynamic(AdditionalFields)
              | extend TagInfo = AF.Tags
              | mv-expand TagInfo
              | extend User = case(
                  isnotempty(AccountUpn), AccountUpn,
                  isnotempty(AF.Name) and AF.Type =~ "account", tostring(AF.Name),
                  ""
              )
              | extend TagName = tostring(TagInfo.TagName)
              | extend Severity = case(
                  TagName == "external_user_risk_tag", "High",
                  "Medium"
              )
              | summarize 
                  HighSeverity = countif(Severity == "High"),
                  MediumSeverity = countif(Severity == "Medium"),
                  LowSeverity = countif(Severity == "Low")
                  by User
            ) on User
            | project 
              User,
              TotalAlerts,
              HighSeverity,
              MediumSeverity,
              LowSeverity
            | sort by TotalAlerts desc

      - Name: DLPAlertsBySeverityAndUser
        DisplayName: Get DLP Alerts by Severity for a Specific User
        Description: Retrieves detailed Data Loss Prevention (DLP) alerts for a specific user, filtered by severity. The query provides insights into matched policies, sensitive information types, associated files, confidence levels, enforced actions, and sender/recipient details. Designed to help analysts identify patterns, consolidate alerts, and prioritize incidents for efficient resolution.
        Inputs:
          - Name: User
            Description: The specific user ID to query DLP alerts for (e.g., user@example.com).
            Required: true
          - Name: Severity
            Description: The severity level to filter the alerts (e.g., High, Medium, Low).
            Required: true
        Settings:
          Target: Defender
          Template: |-
              let user = '{{User}}';
              let severityLevel = '{{Severity}}';
              CloudAppEvents
              | where ActionType has "DLPRuleMatch" 
                  and RawEventData.UserId has user
                  and parse_json(tostring(parse_json(tostring(parse_json(tostring(RawEventData.PolicyDetails))[0].Rules))[0].Severity)) == severityLevel
              | extend PolicyName = tostring(parse_json(tostring(RawEventData.PolicyDetails))[0].PolicyName)
              | extend SensitiveInformationTypeName = tostring(parse_json(tostring(parse_json(tostring(parse_json(tostring(parse_json(tostring(RawEventData.PolicyDetails))[0].Rules))[0].ConditionsMatched)).SensitiveInformation))[0].SensitiveInformationTypeName)
              | extend FileName = tostring(parse_json(tostring(parse_json(tostring(RawEventData.ExchangeMetaData)).AttachmentDetails))[0].Name)
              | extend FileSize = toint(parse_json(tostring(parse_json(tostring(RawEventData.ExchangeMetaData)).AttachmentDetails))[0].Size)
              | extend ConfidenceLevel = toint(parse_json(tostring(parse_json(tostring(parse_json(tostring(parse_json(tostring(RawEventData.PolicyDetails))[0].Rules))[0].ConditionsMatched)).SensitiveInformation))[0].Confidence)
              | extend Actions = tostring(parse_json(tostring(parse_json(tostring(parse_json(tostring(RawEventData.PolicyDetails))[0].Rules))[0])).Actions)
              | extend Recipient = tostring(parse_json(tostring(parse_json(tostring(RawEventData.ExchangeMetaData)).To))[0])
              | extend Sender = tostring(parse_json(tostring(RawEventData.ExchangeMetaData)).From)
              | extend IncidentId = tostring(parse_json(tostring(RawEventData)).IncidentId)
              | extend Timestamp = todatetime(RawEventData.CreationTime)
              | project Timestamp, PolicyName, SensitiveInformationTypeName, FileName, FileSize, ConfidenceLevel, Actions, Sender, Recipient, Severity = severityLevel, UserId = RawEventData.UserId, IncidentId
              | order by Timestamp desc

      - Name: DLPAlertsTopUsersOverview
        DisplayName: Get Top Users Triggering DLP Alerts
        Description: This KQL query analyzes DLP rule matches and alerts from CloudAppEvents, identifying users with the highest sensitive info detections and alert counts across SharePoint, OneDrive, Teams, and Endpoints. It distinguishes between alerts with sensitive information types (higher regulatory risk) and alerts without SITs (potential data exfiltration risks), then aggregates alerts by severity, joins them with sensitive info detections, and ranks the top 10 users with the most DLP incidents to highlight potential compliance violations and security threats.
        Settings:
          Target: Defender
          Template: |-
            let timerange = 30d;                                                      // Define the time range for the query  
            // First create a temporary result of sensitive info counts per user  
            let SensitiveInfoCounts = CloudAppEvents  
            | where TimeGenerated > ago(timerange)                                    // Filter events within the specified time range  
            | where ActionType == "DlpRuleMatch"                                      // Filter for DLP rule match events  
            | extend parsedEventData = parse_json(RawEventData)                       // Parse RawEventData into a structured format  
            | extend Workload = parsedEventData.Workload                              // Extract the workload  
            //| where Workload != "Exchange"                                          // Uncomment Filter out Exchange events
            | extend UserPrincipalName = tostring(parsedEventData.UserId)             // Extract the user principal name  
            | extend PolicyDetails = parsedEventData.PolicyDetails                    // Extract policy details  
            | mv-expand PolicyDetails                                                 // Expand the PolicyDetails array (one row per policy match)  
            | extend Rules = PolicyDetails.Rules                                      // Extract the Rules field  
            | mv-expand Rules                                                         // Expand the Rules array (one row per rule match)  
            | extend ConditionsMatched = parse_json(Rules.ConditionsMatched)          // Parse ConditionsMatched to access sensitive info  
            | extend SensitiveInformation = ConditionsMatched.SensitiveInformation    // Extract the SensitiveInformation array  
            | mv-expand SensitiveInformation                                          // Expand the SensitiveInformation array (one row per type)  
            | where isnotempty(SensitiveInformation)                                  // Remove rows where SensitiveInformation is empty  
            | summarize SensitiveInfoAlertCount = count() by UserPrincipalName;       // Count sensitive info alerts per user  
            // Main query  
            CloudAppEvents  
            | where Timestamp > ago(timerange)                                        // Filter events within the specified time range  
            | extend RawData = parse_json(RawEventData)                               // Parse RawEventData into a structured format  
            | where RawData.Category == "DataLossPrevention"                          // Filter for Data Loss Prevention (DLP) events  
            | where RawData.Operation == "AlertTriggered"                             // Filter for alerts that were triggered  
            | extend DLPAlertId = tostring(RawData.AlertId)                           // Extract the DLP alert ID  
            | extend Data = parse_json(tostring(RawData.Data))                        // Parse the Data field for more details  
            | extend UserPrincipalName = tostring(Data.f3u)                           // Extract the user principal name  
            | extend MessageType = case(                                              // Categorize the type of message  
                Data.wl == "SharePoint" or Data.wl == "OneDrive", "file",  
                Data.wl == "MicrosoftTeams", "teams",  
                Data.wl == "Endpoint", "endpoint",  
                Data.wl == "Exchange", "exchange",  
                "other"  
            )  
            //| where MessageType != "Exchange"                                         // Uncomment this to include exchange alerts
            | extend Severity = tostring(RawData.Severity)                            // Extract severity level of the alert  
            | summarize  
                AlertCount = count(),                                                 // Count total alerts  
                FileAlerts = countif(MessageType == "file"),                          // Count file-related alerts  
                TeamsAlerts = countif(MessageType == "teams"),    
                ExchangeAlerts = countif(MessageType == "exchange"),                  // Count Exchange-related alerts  
                EndpointAlerts = countif(MessageType == "endpoint"),                  // Count endpoint-related alerts  
                ExternalCount = countif(Data.dmc has "IncludeExternalUsers")          // Count alerts involving external users  
                by UserPrincipalName, Severity  
            | summarize  
                AlertsByUser = make_bag(pack(Severity, AlertCount)),                  // Organize alerts by severity  
                FileAlerts = sum(FileAlerts),                                         // Sum of file-related alerts  
                TeamsAlerts = sum(TeamsAlerts),                                       // Sum of Teams-related alerts  
                ExchangeAlerts = sum(ExchangeAlerts),                                 // Sum of Exchange-related alerts  
                EndpointAlerts = sum(EndpointAlerts),                                 // Sum of endpoint-related alerts  
                ExternalCount = sum(ExternalCount),                                   // Sum of alerts involving external users  
                TotalAlerts = sum(AlertCount)                                         // Total alerts per user  
                by UserPrincipalName  
            | extend  
                HighAlerts = tolong(AlertsByUser.High),                               // Extract high-severity alerts count  
                MediumAlerts = tolong(AlertsByUser.Medium),                           // Extract medium-severity alerts count  
                LowAlerts = tolong(AlertsByUser.Low),                                 // Extract low-severity alerts count  
                ExternalPercentage = round((ExternalCount * 100.0 / TotalAlerts), 2)  // Calculate external alerts percentage  
            // Join with the sensitive info counts  
            | lookup SensitiveInfoCounts on UserPrincipalName  
            | project  
                UserPrincipalName,                                                    // User who triggered the alerts  
                TotalAlerts,                                                          // Total number of alerts  
                SensitiveInfoAlertCount = coalesce(SensitiveInfoAlertCount, 0),       // Count of sensitive info alerts per user  
                HighAlerts = coalesce(HighAlerts, 0),                                 // Count of high-severity alerts  
                MediumAlerts = coalesce(MediumAlerts, 0),                             // Count of medium-severity alerts  
                LowAlerts = coalesce(LowAlerts, 0),                                   // Count of low-severity alerts  
                FileAlerts,                                                           // Count of file-related alerts  
                TeamsAlerts,                                                          // Count of Teams-related alerts  
                EndpointAlerts,                                                       // Count of endpoint-related alerts  
                ExchangeAlerts,                                                       // Count of exchange-related alerts  
                ExternalCount,                                                        // Count of alerts involving external users  
                ExternalPercentage                                                    // Percentage of external-related alerts  
            | top 10 by TotalAlerts desc                                              // Retrieve the top 10 users with the most alerts  

      - Name: DLPAlertDetailsWithPurviewLink
        DisplayName: Get Detailed DLP Alert Info with Purview Alert URL
        Description: This query retrieves detailed information about DLP alerts, including alert ID, policy name, severity, user details, and generates a Purview URL for quick navigation.
        Inputs:
          - Name: UPN
            Description: UPN of the user to search
            Required: true   
        Settings:
          Target: Defender          
          Template: |-
            let timerange = 30d;                                                      // Define the time range for the query  
            let searchuser = "{{UPN}}";                                               // Define the user principal name (UPN) to search for  
            CloudAppEvents  
            | where Timestamp > ago(timerange)                                        // Filter events within the specified time range  
            | extend RawData = parse_json(RawEventData)                               // Parse RawEventData into a structured format  
            | where RawData.Category == "DataLossPrevention"                          // Filter for Data Loss Prevention (DLP) events  
            | where RawData.Operation == "AlertTriggered"                             // Filter for alerts that were triggered  
            | extend DataJson = parse_json(tostring(RawData.Data))                    // Parse the Data field for more details  
            | extend  
                User = tostring(DataJson.f3u),                                        // Extract the user who triggered the event  
                Subject = tostring(DataJson.von),                                     // Extract the subject of the event  
                To = tostring(DataJson.["To"]),                                       // Extract recipient information  
                From = tostring(DataJson.mfrm),                                       // Extract sender information  
                Workload = tostring(DataJson.wl)                                      // Extract workload information  
            | where User == searchuser                                                // Filter events specific to the searched user  
            //| where Workload != "Exchange"                                            // Exclude Exchange-related events  
            | project  
                Timestamp,                                                            // When the event occurred  
                User,                                                                 // User who triggered the event  
                Workload,                                                             // Workload associated with the event  
                PolicyName = tostring(RawData.Name),                                  // Name of the DLP policy that triggered the event  
                Severity = tostring(RawData.Severity),                                // Severity level of the alert  
                Subject,                                                              // Email or document subject  
                PurviewURL = strcat("https://purview.microsoft.com/datalossprevention/alertspage/fullpage?tid=",  
                                    tostring(RawEventData.OrganizationId),  
                                    "&alertsviewid=overview&id=",  
                                    tostring(RawData.AlertId))                       // Construct the Purview alert URL  
            | sort by User desc                                                       // Sort results by User in descending order  

      - Name: DLPAlertsSensitiveInfoTypes
        DisplayName: DLP Alerts with Sensitive Information Types
        Description: This query retrieves detailed DLP events, highlighting sensitive information types, detection confidence, impacted files or items, and triggered policies across workloads. It provides security analysts with actionable insights to investigate and mitigate potential data leakage incidents effectively.
        Inputs:
        - Name: UPN
          Description: UPN of the user to search
          Required: true   
        Settings:
          Target: Defender
          Template: |-
            // Define the user principal name (UPN) to search for  
            let searchUser = "{{UPN}}";  
            CloudAppEvents  
            | where ActionType == "DlpRuleMatch"                                      // Filter for DLP rule matches only  
            | where TimeGenerated > ago(30d)                                          // Look at events from the last 30 days  
            | extend parsedEventData = parse_json(RawEventData)                       // Parse the RawEventData JSON field into a structured format  
            | where parsedEventData.UserId == searchUser                              // Filter for events specific to the searched user  
            | extend Workload = parsedEventData.Workload                              // Extract the workload  
            //| where Workload != "Exchange"                                            // Exclude Exchange-related events  
            | extend PolicyDetails = parsedEventData.PolicyDetails                    // Extract DLP policy details  
            | mv-expand PolicyDetails                                                 // Expand the PolicyDetails array (one row per policy match)  
            | extend Rules = PolicyDetails.Rules                                      // Extract the Rules field  
            | mv-expand Rules                                                         // Expand the Rules array (one row per rule match)  
            | extend ConditionsMatched = parse_json(Rules.ConditionsMatched)          // Parse ConditionsMatched to access sensitive info  
            | extend SensitiveInformation = ConditionsMatched.SensitiveInformation    // Extract the SensitiveInformation array  
            | mv-expand SensitiveInformation                                          // Expand the SensitiveInformation array (one row per type)  
            | where isnotempty(SensitiveInformation)                                  // Remove rows where SensitiveInformation is empty  
            | project  
                TimeGenerated,                                                        // When the event occurred  
                UserId = parsedEventData.UserId,                                      // User who triggered the event  
                SensitiveInformationType = SensitiveInformation.SensitiveInformationTypeName, // Type of sensitive info found  
                Confidence = SensitiveInformation.Confidence,                         // Confidence level of the match  
                Count = SensitiveInformation.Count,                                   // Number of instances found  
                Location = SensitiveInformation.Location,                             // Where in the content it was found  
                UniqueCount = SensitiveInformation.UniqueCount,                       // Number of unique instances  
                Workload                                                              // Workload associated with the event  
