O365 Defender SafeLinks - Single User Deprecated

Deprecated. Use O365 Defender SafeLinks instead. Enables URL scanning, rewriting inbound email messages in the mail flow, time-of-click URL verification, and links in email messages and other locations.

Utilities · Microsoft 365 Defender

Details

IDO365 Defender SafeLinks - Single User
ProviderMicrosoft
CategoryUtilities
From Version6.0.0
Docker Imagedemisto/powershell-ubuntu:7.4.1.86201
Supported ModulesAgentix Cloud Runtime Security XSIAM EDR Cortex Cloud

README

Provides URL scanning and rewriting of inbound email messages in mail flow, and time-of-click verification of URLs and links in email messages and other locations.
This integration was integrated and tested with Exchange Online PowerShell V1 module, and Defender for Office 365.

The Safe Links Product overview

Required Permissions


  • To create, modify, and delete Safe Links policies, or use any of the report commands (detailed or aggregate report), you need to be a member of the Organization Management or Security Administrator role groups.
  • To manage permissions in the Microsoft Defender XDR portal, go to Permissions & roles or https://security.microsoft.com/securitypermissions. You need to be a global administrator or a member of the Organization Management role group in the Microsoft Defender XDR portal. Specifically, the Role Management role allows users to view, create, and modify role groups in the Microsoft Defender XDR portal, and by default, that role is assigned only to the Organization Management role group. See Permissions in the Microsoft Defender XDR portal

Configure O365 Defender SafeLinks - Single User in Cortex

Parameter Required
Exchange Online URL True
Email / User Principal Name (Required) False
Password (Required for Basic authentication only) False
Trust any certificate (not secure) False

Safe Links Rule and Policy


The basic elements of a Safe Links policy are:

The safe links policy: Turn on Safe Links protection, turn on real-time URL scanning, specify whether to wait for real-time scanning to complete before delivering the message, turn on scanning for internal messages, specify whether to track user clicks on URLs, and specify whether to allow users to click trough to the original URL.
The safe links rule: Specifies the priority and recipient filters (who the policy applies to).
The difference between these two elements isn’t obvious when you manage Safe Links policies in the Microsoft Defender XDR portal:

When you create a Safe Links policy, you’re actually creating a safe links rule and the associated safe links policy at the same time using the same name for both.
When you modify a Safe Links policy, settings related to the name, priority, enabled or disabled, and recipient filters modify the safe links rule. All other settings modify the associated safe links policy.
When you remove a Safe Links policy, the safe links rule and the associated safe links policy are removed.
In Exchange Online PowerShell or standalone EOP PowerShell, you manage the policy and the rule separately.

Commands

You can execute these commands from the CLI, as part of an automation, or in a playbook.
After you successfully execute a command, a DBot message appears in the War Room with the command details.

o365-defender-safelinks-auth-start


Starts the OAuth2.0 authorization process.

Base Command

o365-defender-safelinks-auth-start

Input

| Argument Name | Description | Required |
| — | — | — |

Context Output

There is no context output for this command.

Command Example


#### Human Readable Output

>## Security And Compliance - Authorize instructions
>
>1. To sign in, use a web browser to open the page [https://microsoft.com/devicelogin](https://microsoft.com/devicelogin) and enter the code **XXXXXXX** to authenticate.
>2. Run the ***!o365-sc-auth-complete*** command in the War Room.

### o365-sc-auth-complete

***
Completes the OAuth2.0 authorization process.

#### Base Command

`o365-defender-safelinks-auth-complete`

#### Input

| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |

#### Context Output

There is no context output for this command.

#### Command Example

```!o365-defender-safelinks-auth-complete```

#### Human Readable Output

>Your account **successfully** authorized!

### o365-defender-safelinks-auth-test

***
Tests the OAuth2.0 authorization process.

#### Base Command

`o365-defender-safelinks-auth-test`

#### Input

| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |

#### Context Output

There is no context output for this command.

#### Command Example

```!o365-defender-safelinks-auth-test```

#### Human Readable Output

>**Test ok!**

### o365-defender-safelinks-policy-list

***
List the Safe Links policies in your cloud-based organization.

#### Base Command

`o365-defender-safelinks-policy-list`

#### Input

| **Argument Name** | **Description** | **Required** |
| --- | --- | --- |
| identity | The identity of the Safe Links policy that you want to view. Available identity fields of the policy are: Name, Distinguished name (DN), and GUID. | Optional |

#### Context Output

| **Path** | **Type** | **Description** |
| --- | --- | --- |
| O365Defender.SafeLinks.AdminDisplayName | String | Policy description. |
| O365Defender.SafeLinks.Policy.AllowClickThrough | Boolean | Whether users are allowed to click through the original URL. |
| O365Defender.SafeLinks.Policy.CustomNotificationText | String | The customized notification text to show to users. |
| O365Defender.SafeLinks.Policy.DeliverMessageAfterScan | Boolean | Whether the mail is delivered after Safe Links scanning was completed. |
| O365Defender.SafeLinks.Policy.DisableUrlRewrite | Boolean | Whether URLs are rewritten \(wrapped\) in email messages. |
| O365Defender.SafeLinks.Policy.DistinguishedName | String | Policy distinguished name \(DN\). |
| O365Defender.SafeLinks.Policy.DoNotAllowClickThrough | Boolean | Whether users can click through the original URLs. |
| O365Defender.SafeLinks.Policy.DoNotTrackUserClicks | Boolean | Whether user clicks are tracked. |
| O365Defender.SafeLinks.Policy.DoNotRewriteUrls | Unknown | List of URLs that are not rewritten by Safe Links scanning. |
| O365Defender.SafeLinks.Policy.EnableForInternalSenders | Boolean | Whether the Safe Links policy is applied to messages sent between internal senders and internal recipients within the same Exchange Online organization. |
| O365Defender.SafeLinks.Policy.EnableOrganizationBranding | Boolean | Whether the organization's logo is displayed on Safe Links warning and notification pages. |
| O365Defender.SafeLinks.Policy.EnableSafeLinksForTeams | Boolean | Whether the Safe Links policy is enabled for Microsoft Teams. |
| O365Defender.SafeLinks.Policy.ExchangeObjectId | String | Exchange object ID. |
| O365Defender.SafeLinks.Policy.ExchangeVersion | String | The version of the Exchange server. |
| O365Defender.SafeLinks.Policy.Guid | String | The GUID of the Safe Links policy. |
| O365Defender.SafeLinks.Policy.Id | String | The ID of the Safe Links policy. |
| O365Defender.SafeLinks.Policy.Identity | String | The identity of the Safe Links policy. |
| O365Defender.SafeLinks.Policy.IsDefault | Boolean | Whether the Safe Links policy is the default policy. |
| O365Defender.SafeLinks.Policy.IsEnabled | Boolean | Whether Safe Links protection is enabled for email messages. |
| O365Defender.SafeLinks.Policy.IsValid | Boolean | Whether the Safe Links policy is valid. |
| O365Defender.SafeLinks.Policy.Name | String | Policy name. |
| O365Defender.SafeLinks.Policy.ObjectState | String | The Safe Links policy state. |
| O365Defender.SafeLinks.Policy.OrganizationId | String | The organization ID. |
| O365Defender.SafeLinks.Policy.ScanUrls | Boolean | Whether real-time scanning of clicked links in email messages is enabled. |
| O365Defender.SafeLinks.Policy.WhenChanged | Date | The date and time the Safe Links policy was modified. Time format: YYYY-MM-DDThh:mm:ss\+00:00. |
| O365Defender.SafeLinks.Policy.WhenChangedUTC | Date | The date and time \(in UTC\) the  Safe Links policy was modified. Time format: YYYY-MM-DDTHH:MM:SSZ. |
| O365Defender.SafeLinks.Policy.WhenCreated | Date | The date and time the Safe Links policy was created. Time format: YYYY-MM-DDThh:mm:ss\+00:00. |
| O365Defender.SafeLinks.Policy.WhenCreatedUTC | Date | The date and time \(in UTC\) the Safe Links policy was created. Time format: YYYY-MM-DDTHH:MM:SSZ. |

#### Command Example

```!o365-defender-safelinks-policy-list```

#### Context Example

```json
{
  "O365Defender.SafeLinks.Policy(obj.Guid === val.Guid)": [
    {
      "AdminDisplayName": "Few URL",
      "AllowClickThrough": true,
      "CustomNotificationText": "Sorry, you cant click through this URL",
      "DeliverMessageAfterScan": false,
      "DisableUrlRewrite": false,
      "DistinguishedName": "CN=XSOAR Policy,CN=Safe Links,CN=Transport Settings,CN=Configuration,CN=xsoartest.onmicrosoft.com,CN=ConfigurationUnits,DC=EURPR07A123,DC=PROD,DC=OUTLOOK,DC=COM",
      "DoNotAllowClickThrough": false,
      "DoNotRewriteUrls": [
        "www.test.com",
        "https://xsoar.test.com"
      ],
      "DoNotTrackUserClicks": false,
      "EnableForInternalSenders": false,
      "EnableOrganizationBranding": false,
      "EnableSafeLinksForTeams": false,
      "ExchangeObjectId": "5796cea3-cfdb-4a99-9956-bf62209118a6",
      "ExchangeVersion": "0.20 (15.0.0.0)",
      "ExcludedUrls": [
        "www.test.com",
        "https://xsoar.test.com"
      ],
      "Guid": "5796cea3-cfdb-4a99-9956-bf62209118a6",
      "Id": "XSOAR Policy",
      "Identity": "XSOAR Policy",
      "IsBuiltInProtection": false,
      "IsDefault": false,
      "IsEnabled": true,
      "IsValid": true,
      "LocalizedNotificationTextList": [
        "[zh-Hant, 對不起,你不能點擊通過這個網址]",
        "[af, Jammer, jy kan nie deur hierdie URL klik nie]",
        "[hi, क्षमा करें, आप इस यूआरएल के माध्यम से क्लिक नहीं कर सकते]",
        "[ja, この URL をクリックできません。]",
        "[otq, Nä'ä di tsa̲hu̲, hingi tsa̲ o̲t'e clic nuna ar URL]",
        "[zh-Hans, 对不起,你不能点击通过这个网址]",
        "[ur, معذرت، آپ اس یو آر ایل کے ذریعے کلک نہیں کر سکتے]",
        "[ht, Padon, ou pa klike sou URL sa a]",
        "[it, Siamo spiacenti, non puoi fare clic su questo URL]",
        "[ms, Maaf, anda tidak boleh klik melalui URL ini]",
        "[bs, Žao mi je, ne možete kliknuti kroz ovaj URL]",
        "[cs, Je nám líto, ale nemůžete kliknout na tuto adresu URL]",
        "[mt, Jiddispjaċina, ma tistax tikklikkja permezz ta' dan il-URL]",
        "[fa, با عرض پوزش، شما نمی توانید از طریق این آدرس کلیک کنید]",
        "[ga, Ár leithscéal, ní féidir leat cliceáil tríd an URL seo]",
        "[da, Beklager, men du kan ikke klikke dig igennem denne URL-adresse]",
        "[hr, Nažalost, ne možete kliknuti kroz ovaj URL]",
        "[he, מצטערים, אתה לא יכול ללחוץ על כתובת URL זו]",
        "[et, Kahjuks ei saa te seda URL-i klõpsata]",
        "[tr, Üzgünüz, bu URL'yi tıklatamazsınız]",
        "[ru, Извините, вы не можете щелкнуть по этому URL-адресу]",
        "[nb, Beklager, du kan ikke klikke deg gjennom denne URL-adressen]",
        "[ar, عذرا، أنت غير قادر على النقر من خلال هذا العنوان]",
        "[fr, Désolé, vous ne pouvez pas cliquer sur cette URL]",
        "[sv, Tyvärr kan du inte klicka igenom den här URL:en]",
        "[tlh-Piqd,      ]",
        "[de, Es tut uns leid, aber Sie können sich nicht durch diese URL klicken]",
        "[id, Maaf, Anda tidak bisa mengklik URL ini]",
        "[kk, Кешіріңіз, осы URL мекенжайы арқылы басуға болмайды]",
        "[lv, Atvainojiet, jūs nevarat noklikšķināt caur šo URL]",
        "[yue, 对唔住,你唔可以點擊透過呢個網址]",
        "[nl, Sorry, u kunt niet door deze URL klikken]",
        "[ro, Ne pare rău, tu cant faceți clic prin acest URL-ul]",
        "[ml, ക്ഷമിക്കണം, ഈ യുആർഎൽ വഴി ക്ലിക്ക് ചെയ്യാൻ നിങ്ങൾക്ക് കഴിയില്ല]",
        "[sw, Samahani, unaweza kubofya kupitia URL hii]",
        "[sl, Žal ne morete klikati preko tega URL-ja]",
        "[th, ขออภัย คุณไม่สามารถคลิกผ่าน URL นี้]",
        "[to, Kātaki fakamolemole, he ʻikai lava ke ke lomiʻi ʻi he URL ko ʻení]",
        "[pt-PT, Desculpe, não pode clicar neste URL]",
        "[ca, Ho sentim, no podeu fer clic a través d'aquesta URL]",
        "[ko, 죄송합니다, 이 URL을 클릭할 수 없습니다.]",
        "[el, Δυστυχώς, δεν μπορείτε να κάνετε κλικ σε αυτήν τη διεύθυνση URL]",
        "[fil, Paumanhin, maaari mong i-click sa pamamagitan ng URL na ito]",
        "[fj, Vosota, e sega ni rawa ni o kiliki ena URL oqo]",
        "[cy, Mae'n ddrwg gennym, gallwch glicio drwy'r URL hwn]",
        "[hu, Sajnáljuk, nem kattinthat át ezen az URL-címen]",
        "[pt, Desculpe, você não pode clicar através desta URL]",
        "[kn, ಕ್ಷಮಿಸಿ, ಈ ಯುಆರ್ ಎಲ್ ಮೂಲಕ ನೀವು ಕ್ಲಿಕ್ ಮಾಡಲು ಸಾಧ್ಯವಿಲ್ಲ]",
        "[pl, Przepraszamy, nie możesz kliknąć tego adresu URL]",
        "[bn, দুঃখিত, আপনি এই ইউআরএল-এর মাধ্যমে ক্লিক করতে পারবেন না]",
        "[vi, Xin lỗi, bạn không thể nhấp qua URL này]",
        "[gu, માફ કરશો, તમે આ યુઆરએલ દ્વારા ક્લિક કરી શકતા નથી]",
        "[sr-Cyrl, Жао нам је, не можете кликнути кроз ову УРЛ адресу]",
        "[sr-Latn, Žao nam je, ne možete kliknuti kroz ovu URL adresu]",
        "[sk, Ľutujeme, nemôžete kliknúť na túto adresu URL]",
        "[en, Sorry, you cant click through this URL]",
        "[uk, На жаль, ви нахиляє натисніть через цю URL-адресу]",
        "[mi, Aroha mai, kāore e taea te pāwhiri mā tēnei URL]",
        "[sm, Faamalie atu, e le mafai ona e kiliki i le URL lenei]",
        "[fi, Valitettavasti et voi napsauttaa tätä URL-osoitetta]",
        "[lt, Atsiprašome, jūs negalite spustelėti per šį URL]",
        "[bg, Съжаляваме, можете да кликнете чрез този URL адрес]",
        "[te, క్షమించండి, ఈ యుఆర్ ఎల్ ద్వారా మీరు క్లిక్ చేయలేరు]",
        "[is, Því miður geturðu ekki smellt í gegnum þessa slóð]",
        "[ta, மன்னிக்கவும், இந்த யுஆர்எல் வழியாக கிளிக் செய்ய முடியாது]",
        "[tlh-Latn, taHqeq mIv'a' tIqwIj, qaStaHvIS poH nI''e']",
        "[mww, Thov txim, koj yuav nias los ntawm no URL]",
        "[es, Lo sentimos, no puedes hacer clic en esta URL]",
        "[pa, ਮਾਫ਼ ਕਰਨਾ, ਤੁਸੀਂ ਇਸ ਯੂਆਰਐਲ ਰਾਹੀਂ ਕਲਿੱਕ ਨਹੀਂ ਕਰ ਸਕਦੇ]",
        "[mg, Miala tsiny fa tsy afaka manindry ity URL ity ianao]"
      ],
      "Name": "XSOAR Policy",
      "ObjectCategory": "EURPR07A123.PROD.OUTLOOK.COM/Configuration/Schema/ms-Exch-Smart-Links-Protection-Config",
      "ObjectClass": [
        "top",
        "msExchSmartLinksProtectionConfig"
      ],
      "ObjectState": "Unchanged",
      "OrganizationId": "EURPR07A123.PROD.OUTLOOK.COM/Microsoft Exchange Hosted Organizations/xsoartest.onmicrosoft.com - EURPR07A123.PROD.OUTLOOK.COM/ConfigurationUnits/xsoartest.onmicrosoft.com/Configuration",
      "OrganizationalUnitRoot": "xsoartest.onmicrosoft.com",
      "OriginatingServer": "AM7PR07A05DC123.EURPR07A123.PROD.OUTLOOK.COM",
      "PSComputerName": "outlook.office365.com",
      "PSShowComputerName": false,
      "RecommendedPolicyType": "Custom",
      "RunspaceId": "8501abb8-6d7c-45ca-bc0d-4c260d68d248",
      "ScanUrls": false,
      "TrackClicks": true,
      "WhenChanged": "2021-10-21T12:49:09+00:00",
      "WhenChangedUTC": "2021-10-21T12:49:09Z",
      "WhenCreated": "2021-10-21T12:49:03+00:00",
      "WhenCreatedUTC": "2021-10-21T12:49:03Z",
      "WhiteListedUrls": "www.test.com,https://xsoar.test.com"
    }
  ]
}

Human Readable Output

Results of o365-defender-safelinks-policy-list

AdminDisplayName AllowClickThrough CustomNotificationText DeliverMessageAfterScan DisableUrlRewrite DistinguishedName DoNotAllowClickThrough DoNotRewriteUrls DoNotTrackUserClicks EnableForInternalSenders EnableOrganizationBranding EnableSafeLinksForTeams ExchangeObjectId ExchangeVersion ExcludedUrls Guid Id Identity IsBuiltInProtection IsDefault IsEnabled IsValid LocalizedNotificationTextList Name ObjectCategory ObjectClass ObjectState OrganizationalUnitRoot OrganizationId OriginatingServer PSComputerName PSShowComputerName RecommendedPolicyType RunspaceId ScanUrls TrackClicks WhenChanged WhenChangedUTC WhenCreated WhenCreatedUTC WhiteListedUrls
Few URL true Sorry, you cant click through this URL false false CN=XSOAR Policy,CN=Safe Links,CN=Transport Settings,CN=Configuration,CN=xsoartest.onmicrosoft.com,CN=ConfigurationUnits,DC=EURPR07A123,DC=PROD,DC=OUTLOOK,DC=COM false [“www.test.com”,”https://xsoar.test.com”] false false false false {“value”:”5796cea3-cfdb-4a99-9956-bf62209118a6”,”Guid”:”5796cea3-cfdb-4a99-9956-bf62209118a6”} 0.20 (15.0.0.0) [“www.test.com”,”https://xsoar.test.com”] {“value”:”5796cea3-cfdb-4a99-9956-bf62209118a6”,”Guid”:”5796cea3-cfdb-4a99-9956-bf62209118a6”} XSOAR Policy XSOAR Policy false false true true [“[zh-Hant, 對不起,你不能點擊通過這個網址]”,”[af, Jammer, jy kan nie deur hierdie URL klik nie]”,”[hi, क्षमा करें, आप इस यूआरएल के माध्यम से क्लिक नहीं कर सकते]”,”[ja, この URL をクリックできません。]”,”[otq, Nä’ä di tsa̲hu̲, hingi tsa̲ o̲t’e clic nuna ar URL]”,”[zh-Hans, 对不起,你不能点击通过这个网址]”,”[ur, معذرت، آپ اس یو آر ایل کے ذریعے کلک نہیں کر سکتے]”,”[ht, Padon, ou pa klike sou URL sa a]”,”[it, Siamo spiacenti, non puoi fare clic su questo URL]”,”[ms, Maaf, anda tidak boleh klik melalui URL ini]”,”[bs, Žao mi je, ne možete kliknuti kroz ovaj URL]”,”[cs, Je nám líto, ale nemůžete kliknout na tuto adresu URL]”,”[mt, Jiddispjaċina, ma tistax tikklikkja permezz ta’ dan il-URL]”,”[fa, با عرض پوزش، شما نمی توانید از طریق این آدرس کلیک کنید]”,”[ga, Ár leithscéal, ní féidir leat cliceáil tríd an URL seo]”,”[da, Beklager, men du kan ikke klikke dig igennem denne URL-adresse]”,”[hr, Nažalost, ne možete kliknuti kroz ovaj URL]”,”[he, מצטערים, אתה לא יכול ללחוץ על כתובת URL זו]”,”[et, Kahjuks ei saa te seda URL-i klõpsata]”,”[tr, Üzgünüz, bu URL’yi tıklatamazsınız]”,”[ru, Извините, вы не можете щелкнуть по этому URL-адресу]”,”[nb, Beklager, du kan ikke klikke deg gjennom denne URL-adressen]”,”[ar, عذرا، أنت غير قادر على النقر من خلال هذا العنوان]”,”[fr, Désolé, vous ne pouvez pas cliquer sur cette URL]”,”[sv, Tyvärr kan du inte klicka igenom den här URL:en]”,”[tlh-Piqd,      ]”,”[de, Es tut uns leid, aber Sie können sich nicht durch diese URL klicken]”,”[id, Maaf, Anda tidak bisa mengklik URL ini]”,”[kk, Кешіріңіз, осы URL мекенжайы арқылы басуға болмайды]”,”[lv, Atvainojiet, jūs nevarat noklikšķināt caur šo URL]”,”[yue, 对唔住,你唔可以點擊透過呢個網址]”,”[nl, Sorry, u kunt niet door deze URL klikken]”,”[ro, Ne pare rău, tu cant faceți clic prin acest URL-ul]”,”[ml, ക്ഷമിക്കണം, ഈ യുആർഎൽ വഴി ക്ലിക്ക് ചെയ്യാൻ നിങ്ങൾക്ക് കഴിയില്ല]”,”[sw, Samahani, unaweza kubofya kupitia URL hii]”,”[sl, Žal ne morete klikati preko tega URL-ja]”,”[th, ขออภัย คุณไม่สามารถคลิกผ่าน URL นี้]”,”[to, Kātaki fakamolemole, he ʻikai lava ke ke lomiʻi ʻi he URL ko ʻení]”,”[pt-PT, Desculpe, não pode clicar neste URL]”,”[ca, Ho sentim, no podeu fer clic a través d’aquesta URL]”,”[ko, 죄송합니다, 이 URL을 클릭할 수 없습니다.]”,”[el, Δυστυχώς, δεν μπορείτε να κάνετε κλικ σε αυτήν τη διεύθυνση URL]”,”[fil, Paumanhin, maaari mong i-click sa pamamagitan ng URL na ito]”,”[fj, Vosota, e sega ni rawa ni o kiliki ena URL oqo]”,”[cy, Mae’n ddrwg gennym, gallwch glicio drwy’r URL hwn]”,”[hu, Sajnáljuk, nem kattinthat át ezen az URL-címen]”,”[pt, Desculpe, você não pode clicar através desta URL]”,”[kn, ಕ್ಷಮಿಸಿ, ಈ ಯುಆರ್ ಎಲ್ ಮೂಲಕ ನೀವು ಕ್ಲಿಕ್ ಮಾಡಲು ಸಾಧ್ಯವಿಲ್ಲ]”,”[pl, Przepraszamy, nie możesz kliknąć tego adresu URL]”,”[bn, দুঃখিত, আপনি এই ইউআরএল-এর মাধ্যমে ক্লিক করতে পারবেন না]”,”[vi, Xin lỗi, bạn không thể nhấp qua URL này]”,”[gu, માફ કરશો, તમે આ યુઆરએલ દ્વારા ક્લિક કરી શકતા નથી]”,”[sr-Cyrl, Жао нам је, не можете кликнути кроз ову УРЛ адресу]”,”[sr-Latn, Žao nam je, ne možete kliknuti kroz ovu URL adresu]”,”[sk, Ľutujeme, nemôžete kliknúť na túto adresu URL]”,”[en, Sorry, you cant click through this URL]”,”[uk, На жаль, ви нахиляє натисніть через цю URL-адресу]”,”[mi, Aroha mai, kāore e taea te pāwhiri mā tēnei URL]”,”[sm, Faamalie atu, e le mafai ona e kiliki i le URL lenei]”,”[fi, Valitettavasti et voi napsauttaa tätä URL-osoitetta]”,”[lt, Atsiprašome, jūs negalite spustelėti per šį URL]”,”[bg, Съжаляваме, можете да кликнете чрез този URL адрес]”,”[te, క్షమించండి, ఈ యుఆర్ ఎల్ ద్వారా మీరు క్లిక్ చేయలేరు]”,”[is, Því miður geturðu ekki smellt í gegnum þessa slóð]”,”[ta, மன்னிக்கவும், இந்த யுஆர்எல் வழியாக கிளிக் செய்ய முடியாது]”,”[tlh-Latn, taHqeq mIv’a’ tIqwIj, qaStaHvIS poH nI’‘e’]”,”[mww, Thov txim, koj yuav nias los ntawm no URL]”,”[es, Lo sentimos, no puedes hacer clic en esta URL]”,”[pa, ਮਾਫ਼ ਕਰਨਾ, ਤੁਸੀਂ ਇਸ ਯੂਆਰਐਲ ਰਾਹੀਂ ਕਲਿੱਕ ਨਹੀਂ ਕਰ ਸਕਦੇ]”,”[mg, Miala tsiny fa tsy afaka manindry ity URL ity ianao]”] XSOAR Policy EURPR07A123.PROD.OUTLOOK.COM/Configuration/Schema/ms-Exch-Smart-Links-Protection-Config [“top”,”msExchSmartLinksProtectionConfig”] Unchanged xsoartest.onmicrosoft.com EURPR07A123.PROD.OUTLOOK.COM/Microsoft Exchange Hosted Organizations/xsoartest.onmicrosoft.com - EURPR07A123.PROD.OUTLOOK.COM/ConfigurationUnits/xsoartest.onmicrosoft.com/Configuration AM7PR07A05DC123.EURPR07A123.PROD.OUTLOOK.COM outlook.office365.com false Custom {“value”:”8501abb8-6d7c-45ca-bc0d-4c260d68d248”,”Guid”:”8501abb8-6d7c-45ca-bc0d-4c260d68d248”} false true {“value”:”2021-10-21T12:49:09+00:00”,”DateTime”:”Thursday, October 21, 2021 12:49:09 PM”} {“value”:”2021-10-21T12:49:09Z”,”DateTime”:”Thursday, October 21, 2021 12:49:09 PM”} {“value”:”2021-10-21T12:49:03+00:00”,”DateTime”:”Thursday, October 21, 2021 12:49:03 PM”} {“value”:”2021-10-21T12:49:03Z”,”DateTime”:”Thursday, October 21, 2021 12:49:03 PM”} www.test.com,https://xsoar.test.com

o365-defender-safelinks-policy-create


Create a new Safe Links policy.

Base Command

o365-defender-safelinks-policy-create

Input

Argument Name Description Required
name A unique name for the Safe Links policy. Required
admin_display_name The description for the policy. Optional
custom_notification_text The custom notification text to show to users. Optional
deliver_message_after_scan Whether to deliver email messages only after Safe Links scanning was completed. When true, messages that contain malicious links are not delivered. Default is false. Possible values are: true, false. Optional
do_not_allow_click_through Whether to allow users to click through to the original URL on warning pages. Default is false. Possible values are: true, false. Optional
do_not_rewrite_urls Comma-separated list of URLs that are not rewritten by Safe Links scanning. Optional
do_not_track_user_clicks Whether to track user clicks related to Safe Links protection of links in email messages. Default is false. Possible values are: true, false. Optional
enable_for_internal_senders Whether the Safe Links policy is applied to messages sent between internal senders and internal recipients within the same Exchange Online organization.Default is false. Possible values are: true, false. Optional
enable_organization_branding Whether to display the organization’s logo on Safe Links warning and notification pages. Default is false. Possible values are: true, false. Optional
enable_safe_links_for_teams Whether to enable Safe Links for Microsoft Teams. Default is false. Possible values are: true, false. Optional
is_enabled Whether to enable Safe Links protection for email messages. Default is false. Possible values are: true, false. Optional
scan_urls Whether to enable or disable real-time scanning of clicked links in email messages. Default is false. Possible values are: true, false. Optional
use_translated_notification_text Whether to use Microsoft Translator to automatically localize the custom notification text that you specified with the CustomNotificationText parameter. Default is false. Possible values are: true, false. Optional

Context Output

Path Type Description
O365Defender.SafeLinks.AdminDisplayName String Policy description.
O365Defender.SafeLinks.Policy.AllowClickThrough Boolean Whether users are allowed to click through the original URL.
O365Defender.SafeLinks.Policy.CustomNotificationText String The customized notification text to show to users.
O365Defender.SafeLinks.Policy.DeliverMessageAfterScan Boolean Whether the mail is delivered after Safe Links scanning was completed.
O365Defender.SafeLinks.Policy.DisableUrlRewrite Boolean Whether URLs are rewritten (wrapped) in email messages.
O365Defender.SafeLinks.Policy.DistinguishedName String Policy distinguished name (DN).
O365Defender.SafeLinks.Policy.DoNotAllowClickThrough Boolean Whether users can click through the original URLs.
O365Defender.SafeLinks.Policy.DoNotTrackUserClicks Boolean Whether user clicks are tracked.
O365Defender.SafeLinks.Policy.DoNotRewriteUrls Unknown List of URLs that are not rewritten by Safe Links scanning.
O365Defender.SafeLinks.Policy.EnableForInternalSenders Boolean Whether the Safe Links policy is applied to messages sent between internal senders and internal recipients within the same Exchange Online organization.
O365Defender.SafeLinks.Policy.EnableOrganizationBranding Boolean Whether the organization’s logo is displayed on Safe Links warning and notification pages.
O365Defender.SafeLinks.Policy.EnableSafeLinksForTeams Boolean Whether the Safe Links policy is enabled for Microsoft Teams.
O365Defender.SafeLinks.Policy.ExchangeObjectId String Exchange object ID.
O365Defender.SafeLinks.Policy.ExchangeVersion String The version of the Exchange server.
O365Defender.SafeLinks.Policy.Guid String The GUID of the Safe Links policy.
O365Defender.SafeLinks.Policy.Id String The ID of the Safe Links policy.
O365Defender.SafeLinks.Policy.Identity String The identity of the Safe Links policy.
O365Defender.SafeLinks.Policy.IsDefault Boolean Whether the Safe Links policy is the default policy.
O365Defender.SafeLinks.Policy.IsEnabled Boolean Whether Safe Links protection is enabled for email messages.
O365Defender.SafeLinks.Policy.IsValid Boolean Whether the Safe Links policy is valid.
O365Defender.SafeLinks.Policy.Name String Policy name.
O365Defender.SafeLinks.Policy.ObjectState String The Safe Links policy state.
O365Defender.SafeLinks.Policy.OrganizationId String The organization ID.
O365Defender.SafeLinks.Policy.ScanUrls Boolean Whether real-time scanning of clicked links in email messages is enabled.
O365Defender.SafeLinks.Policy.WhenChanged Date The date and time the Safe Links policy was modified. Time format: YYYY-MM-DDThh:mm:ss+00:00.
O365Defender.SafeLinks.Policy.WhenChangedUTC Date The date and time (in UTC) the Safe Links policy was modified. Time format: YYYY-MM-DDTHH:MM:SSZ
O365Defender.SafeLinks.Policy.WhenCreated Date The date and time the Safe Links policy was created. Time format: YYYY-MM-DDThh:mm:ss+00:00.
O365Defender.SafeLinks.Policy.WhenCreatedUTC Date The date and time (in UTC) the Safe Links policy was created. Time format: YYYY-MM-DDTHH:MM:SSZ

Command Example

o365-defender-safelinks-policy-create name=xsoartest admin_display_name="Description for policy" do_not_allow_click_through=true

Context Example

{
  "O365Defender.SafeLinks.Policy(obj.Guid === val.Guid)": [
    {
      "AdminDisplayName": "Few URL",
      "AllowClickThrough": true,
      "CustomNotificationText": "Sorry, you cant click through this URL",
      "DeliverMessageAfterScan": false,
      "DisableUrlRewrite": false,
      "DistinguishedName": "CN=xsoartest,CN=Safe Links,CN=Transport Settings,CN=Configuration,CN=xsoartest.onmicrosoft.com,CN=ConfigurationUnits,DC=EURPR07A123,DC=PROD,DC=OUTLOOK,DC=COM",
      "DoNotAllowClickThrough": false,
      "DoNotRewriteUrls": [
        "www.test.com",
        "https://xsoar.test.com"
      ],
      "DoNotTrackUserClicks": false,
      "EnableForInternalSenders": false,
      "EnableOrganizationBranding": false,
      "EnableSafeLinksForTeams": false,
      "ExchangeObjectId": "5796cea3-cfdb-4a99-9956-bf62209118a6",
      "ExchangeVersion": "0.20 (15.0.0.0)",
      "ExcludedUrls": [
        "www.test.com",
        "https://xsoar.test.com"
      ],
      "Guid": "5796cea3-cfdb-4a99-9956-bf62209118a6",
      "Id": "xsoartest",
      "Identity": "xsoartest",
      "IsBuiltInProtection": false,
      "IsDefault": false,
      "IsEnabled": true,
      "IsValid": true,
      "LocalizedNotificationTextList": [],
      "Name": "xsoartest",
      "ObjectCategory": "EURPR07A123.PROD.OUTLOOK.COM/Configuration/Schema/ms-Exch-Smart-Links-Protection-Config",
      "ObjectClass": [
        "top",
        "msExchSmartLinksProtectionConfig"
      ],
      "ObjectState": "Unchanged",
      "OrganizationId": "EURPR07A123.PROD.OUTLOOK.COM/Microsoft Exchange Hosted Organizations/xsoartest.onmicrosoft.com - EURPR07A123.PROD.OUTLOOK.COM/ConfigurationUnits/xsoartest.onmicrosoft.com/Configuration",
      "OrganizationalUnitRoot": "xsoartest.onmicrosoft.com",
      "OriginatingServer": "AM7PR07A05DC123.EURPR07A123.PROD.OUTLOOK.COM",
      "PSComputerName": "outlook.office365.com",
      "PSShowComputerName": false,
      "RecommendedPolicyType": "Custom",
      "RunspaceId": "8501abb8-6d7c-45ca-bc0d-4c260d68d248",
      "ScanUrls": false,
      "TrackClicks": true,
      "WhenChanged": "2021-10-21T12:49:09+00:00",
      "WhenChangedUTC": "2021-10-21T12:49:09Z",
      "WhenCreated": "2021-10-21T12:49:03+00:00",
      "WhenCreatedUTC": "2021-10-21T12:49:03Z",
      "WhiteListedUrls": "www.test.com,https://xsoar.test.com"
    }
  ]
}

Human Readable Output

Results of o365-defender-safelinks-policy-create

AdminDisplayName AllowClickThrough CustomNotificationText DeliverMessageAfterScan DisableUrlRewrite DistinguishedName DoNotAllowClickThrough DoNotRewriteUrls DoNotTrackUserClicks EnableForInternalSenders EnableOrganizationBranding EnableSafeLinksForTeams ExchangeObjectId ExchangeVersion ExcludedUrls Guid Id Identity IsBuiltInProtection IsDefault IsEnabled IsValid LocalizedNotificationTextList Name ObjectCategory ObjectClass ObjectState OrganizationalUnitRoot OrganizationId OriginatingServer PSComputerName PSShowComputerName RecommendedPolicyType RunspaceId ScanUrls TrackClicks WhenChanged WhenChangedUTC WhenCreated WhenCreatedUTC WhiteListedUrls
Few URL true Sorry, you cant click through this URL false false CN=XSOAR Policy,CN=Safe Links,CN=Transport Settings,CN=Configuration,CN=xsoartest.onmicrosoft.com,CN=ConfigurationUnits,DC=EURPR07A123,DC=PROD,DC=OUTLOOK,DC=COM false   XSOAR Policy EURPR07A123.PROD.OUTLOOK.COM/Configuration/Schema/ms-Exch-Smart-Links-Protection-Config [“top”,”msExchSmartLinksProtectionConfig”] Unchanged xsoartest.onmicrosoft.com EURPR07A123.PROD.OUTLOOK.COM/Microsoft Exchange Hosted Organizations/xsoartest.onmicrosoft.com - EURPR07A123.PROD.OUTLOOK.COM/ConfigurationUnits/xsoartest.onmicrosoft.com/Configuration AM7PR07A05DC123.EURPR07A123.PROD.OUTLOOK.COM outlook.office365.com false Custom {“value”:”8501abb8-6d7c-45ca-bc0d-4c260d68d248”,”Guid”:”8501abb8-6d7c-45ca-bc0d-4c260d68d248”} false true {“value”:”2021-10-21T12:49:09+00:00”,”DateTime”:”Thursday, October 21, 2021 12:49:09 PM”} {“value”:”2021-10-21T12:49:09Z”,”DateTime”:”Thursday, October 21, 2021 12:49:09 PM”} {“value”:”2021-10-21T12:49:03+00:00”,”DateTime”:”Thursday, October 21, 2021 12:49:03 PM”} {“value”:”2021-10-21T12:49:03Z”,”DateTime”:”Thursday, October 21, 2021 12:49:03 PM”} www.test.com,https://xsoar.test.com                              

o365-defender-safelinks-policy-update


Update a Safe Links policy.

Base Command

o365-defender-safelinks-policy-update

Input

Argument Name Description Required
name A unique name for the Safe Links policy. Required
admin_display_name The description for the policy. Optional
custom_notification_text The custom notification text to show to users. Optional
deliver_message_after_scan Whether to deliver email messages only after Safe Links scanning was completed. When true, messages that contain malicious links are not delivered. Default is false. Possible values are: true, false. Optional
do_not_allow_click_through Whether to allow users to click through to the original URL on warning pages. Default is false. Possible values are: true, false. Optional
do_not_rewrite_urls Comma-separated list of URLs that are not rewritten by Safe Links scanning. Optional
do_not_track_user_clicks Whether to track user clicks related to Safe Links protection of links in email messages. Default is false. Possible values are: true, false. Optional
enable_for_internal_senders Whether the Safe Links policy is applied to messages sent between internal senders and internal recipients within the same Exchange Online organization. Default is false. Possible values are: true, false. Optional
enable_organization_branding Whether to display the organization’s logo on Safe Links warning and notification pages. Default is false. Possible values are: true, false. Optional
enable_safe_links_for_teams Whether to enable the Safe Links for Microsoft Teams. Default is false. Possible values are: true, false. Optional
is_enabled Whether to enable Safe Links protection for email messages. Default is false. Possible values are: true, false. Optional
scan_urls Whether to enable or disable real-time scanning of clicked links in email messages. Default is false. Possible values are: true, false. Optional
use_translated_notification_text Whether to use Microsoft Translator to automatically localize the custom notification text that you specified with the CustomNotificationText parameter. Default is false. Possible values are: true, false. Optional

Context Output

Path Type Description
O365Defender.SafeLinks.AdminDisplayName String Policy description.
O365Defender.SafeLinks.Policy.AllowClickThrough Boolean Whether users are allowed to click through the original URL.
O365Defender.SafeLinks.Policy.CustomNotificationText String The customized notification text to show to users.
O365Defender.SafeLinks.Policy.DeliverMessageAfterScan Boolean Whether the mail is delivered after Safe Links scanning was completed.
O365Defender.SafeLinks.Policy.DisableUrlRewrite Boolean Whether URLs are rewritten (wrapped) in email messages.
O365Defender.SafeLinks.Policy.DistinguishedName String Policy distinguished name (DN).
O365Defender.SafeLinks.Policy.DoNotAllowClickThrough Boolean Whether users can click through the original URLs.
O365Defender.SafeLinks.Policy.DoNotTrackUserClicks Boolean Whether user clicks are tracked.
O365Defender.SafeLinks.Policy.DoNotRewriteUrls Unknown List of URLs that are not rewritten by Safe Links scanning.
O365Defender.SafeLinks.Policy.EnableForInternalSenders Boolean Whether the Safe Links policy is applied to messages sent between internal senders and internal recipients within the same Exchange Online organization.
O365Defender.SafeLinks.Policy.EnableOrganizationBranding Boolean whether the organization’s logo is displayed on Safe Links warning and notification pages.
O365Defender.SafeLinks.Policy.EnableSafeLinksForTeams Boolean Whether the Safe Links policy is enabled for Microsoft Teams.
O365Defender.SafeLinks.Policy.ExchangeObjectId String Exchange object ID.
O365Defender.SafeLinks.Policy.ExchangeVersion String The version of the Exchange server.
O365Defender.SafeLinks.Policy.Guid String The GUID of the Safe Links policy.
O365Defender.SafeLinks.Policy.Id String The ID of the Safe Links policy.
O365Defender.SafeLinks.Policy.Identity String The identity of the Safe Links policy.
O365Defender.SafeLinks.Policy.IsDefault Boolean Whether the Safe Links policy is the default policy.
O365Defender.SafeLinks.Policy.IsEnabled Boolean Whether Safe Links protection is enabled for email messages.
O365Defender.SafeLinks.Policy.IsValid Boolean Whether the Safe Links policy is valid.
O365Defender.SafeLinks.Policy.Name String Policy name.
O365Defender.SafeLinks.Policy.ObjectState String The Safe Links policy state.
O365Defender.SafeLinks.Policy.OrganizationId String The organization ID.
O365Defender.SafeLinks.Policy.ScanUrls Boolean Whether real-time scanning of clicked links in email messages is enabled.
O365Defender.SafeLinks.Policy.WhenChanged Date The date and time the Safe Links policy was modified. Time format: YYYY-MM-DDThh:mm:ss+00:00.
O365Defender.SafeLinks.Policy.WhenChangedUTC Date The date and time (in UTC) the Safe Links policy was modified. Time format: YYYY-MM-DDTHH:MM:SSZ.
O365Defender.SafeLinks.Policy.WhenCreated Date The date and time the Safe Links policy was created. Time format: YYYY-MM-DDThh:mm:ss+00:00.
O365Defender.SafeLinks.Policy.WhenCreatedUTC Date The date and time (in UTC) the Safe Links policy was created. Time format: YYYY-MM-DDTHH:MM:SSZ.

Command Example

o365-defender-safelinks-policy-update name=xsoartest admin_display_name="Description for policy" do_not_allow_click_through=true

Context Example

{
  "O365Defender.SafeLinks.Policy(obj.Guid === val.Guid)": [
    {
      "AdminDisplayName": "Description for policy",
      "AllowClickThrough": true,
      "CustomNotificationText": "Sorry, you cant click through this URL",
      "DeliverMessageAfterScan": false,
      "DisableUrlRewrite": false,
      "DistinguishedName": "CN=xsoartest policy,CN=Safe Links,CN=Transport Settings,CN=Configuration,CN=xsoartest.onmicrosoft.com,CN=ConfigurationUnits,DC=EURPR07A123,DC=PROD,DC=OUTLOOK,DC=COM",
      "DoNotAllowClickThrough": false,
      "DoNotRewriteUrls": [
        "www.test.com",
        "https://xsoar.test.com"
      ],
      "DoNotTrackUserClicks": false,
      "EnableForInternalSenders": false,
      "EnableOrganizationBranding": false,
      "EnableSafeLinksForTeams": false,
      "ExchangeObjectId": "5796cea3-cfdb-4a99-9956-bf62209118a6",
      "ExchangeVersion": "0.20 (15.0.0.0)",
      "ExcludedUrls": [
        "www.test.com",
        "https://xsoar.test.com"
      ],
      "Guid": "5796cea3-cfdb-4a99-9956-bf62209118a6",
      "Id": "xsoartest policy",
      "Identity": "xsoartest policy",
      "IsBuiltInProtection": false,
      "IsDefault": false,
      "IsEnabled": true,
      "IsValid": true,
      "LocalizedNotificationTextList": [],
      "Name": "xsoartest",
      "ObjectCategory": "EURPR07A123.PROD.OUTLOOK.COM/Configuration/Schema/ms-Exch-Smart-Links-Protection-Config",
      "ObjectClass": [
        "top",
        "msExchSmartLinksProtectionConfig"
      ],
      "ObjectState": "Unchanged",
      "OrganizationId": "EURPR07A123.PROD.OUTLOOK.COM/Microsoft Exchange Hosted Organizations/xsoartest.onmicrosoft.com - EURPR07A123.PROD.OUTLOOK.COM/ConfigurationUnits/xsoartest.onmicrosoft.com/Configuration",
      "OrganizationalUnitRoot": "xsoartest.onmicrosoft.com",
      "OriginatingServer": "AM7PR07A05DC123.EURPR07A123.PROD.OUTLOOK.COM",
      "PSComputerName": "outlook.office365.com",
      "PSShowComputerName": false,
      "RecommendedPolicyType": "Custom",
      "RunspaceId": "8501abb8-6d7c-45ca-bc0d-4c260d68d248",
      "ScanUrls": false,
      "TrackClicks": true,
      "WhenChanged": "2021-10-21T12:49:09+00:00",
      "WhenChangedUTC": "2021-10-21T12:49:09Z",
      "WhenCreated": "2021-10-21T12:49:03+00:00",
      "WhenCreatedUTC": "2021-10-21T12:49:03Z",
      "WhiteListedUrls": "www.test.com,https://xsoar.test.com"
    }
  ]
}

Human Readable Output

Results of o365-defender-safelinks-policy-list

AdminDisplayName AllowClickThrough CustomNotificationText DeliverMessageAfterScan DisableUrlRewrite DistinguishedName DoNotAllowClickThrough DoNotRewriteUrls DoNotTrackUserClicks EnableForInternalSenders EnableOrganizationBranding EnableSafeLinksForTeams ExchangeObjectId ExchangeVersion ExcludedUrls Guid Id Identity IsBuiltInProtection IsDefault IsEnabled IsValid LocalizedNotificationTextList Name ObjectCategory ObjectClass ObjectState OrganizationalUnitRoot OrganizationId OriginatingServer PSComputerName PSShowComputerName RecommendedPolicyType RunspaceId ScanUrls TrackClicks WhenChanged WhenChangedUTC WhenCreated WhenCreatedUTC WhiteListedUrls
Few URL true Sorry, you cant click through this URL false false CN=XSOAR Policy,CN=Safe Links,CN=Transport Settings,CN=Configuration,CN=xsoartest.onmicrosoft.com,CN=ConfigurationUnits,DC=EURPR07A123,DC=PROD,DC=OUTLOOK,DC=COM false   XSOAR Policy EURPR07A123.PROD.OUTLOOK.COM/Configuration/Schema/ms-Exch-Smart-Links-Protection-Config [“top”,”msExchSmartLinksProtectionConfig”] Unchanged xsoartest.onmicrosoft.com EURPR07A123.PROD.OUTLOOK.COM/Microsoft Exchange Hosted Organizations/xsoartest.onmicrosoft.com - EURPR07A123.PROD.OUTLOOK.COM/ConfigurationUnits/xsoartest.onmicrosoft.com/Configuration AM7PR07A05DC123.EURPR07A123.PROD.OUTLOOK.COM outlook.office365.com false Custom {“value”:”8501abb8-6d7c-45ca-bc0d-4c260d68d248”,”Guid”:”8501abb8-6d7c-45ca-bc0d-4c260d68d248”} false true {“value”:”2021-10-21T12:49:09+00:00”,”DateTime”:”Thursday, October 21, 2021 12:49:09 PM”} {“value”:”2021-10-21T12:49:09Z”,”DateTime”:”Thursday, October 21, 2021 12:49:09 PM”} {“value”:”2021-10-21T12:49:03+00:00”,”DateTime”:”Thursday, October 21, 2021 12:49:03 PM”} {“value”:”2021-10-21T12:49:03Z”,”DateTime”:”Thursday, October 21, 2021 12:49:03 PM”} www.test.com,https://xsoar.test.com                              

o365-defender-safelinks-policy-remove


Remove a Safe Links policy.

Base Command

o365-defender-safelinks-policy-remove

Input

Argument Name Description Required
identity The identity of the Safe Links policy that you want to remove. Available identity fields of the policy are: Name, Distinguished name (DN), and GUID. Required

Context Output

There is no context output for this command.

Command Example

!o365-defender-safelinks-policy-remove identity=XsoarTest

Human Readable Output

Policy with Identity: XsoarTest was removed succesfully

o365-defender-safelinks-rule-list


List Safe Links rules in your cloud-based organization.

Base Command

o365-defender-safelinks-rule-list

Input

Argument Name Description Required
identity The identity of the Safe Links rule that you want to view. Available identity fields are: Name, Distinguished name (DN), and GUID. Optional
state The state of the rules. Possible values are: Enabled, Disabled. Optional

Context Output

Path Type Description
O365Defender.SafeLinks.Rule.Comments Unknown Informative comments for the rule, such as what the rule is used for or how it has changed over time. The length of the comment cannot exceed 1024 characters.
O365Defender.SafeLinks.Rule.Conditions String The rule condition.
O365Defender.SafeLinks.Rule.Description String The description of the rule.
O365Defender.SafeLinks.Rule.DistinguishedName String Rule distinguished name (DN).
O365Defender.SafeLinks.Rule.ExceptIfRecipientDomainIs Unknown Recipients with email address in the specified domains are excluded.
O365Defender.SafeLinks.Rule.ExceptIfSentTo Unknown Recipients to be excluded.
O365Defender.SafeLinks.Rule.ExceptIfSentToMemberOf Unknown Recipients in these groups are excluded.
O365Defender.SafeLinks.Rule.Exceptions Unknown Rule exceptions.
O365Defender.SafeLinks.Rule.Guid String The GUID of the rule.
O365Defender.SafeLinks.Rule.Identity String The identity of the Safe Links rule.
O365Defender.SafeLinks.Rule.IsValid Boolean Whether the rule is valid.
O365Defender.SafeLinks.Rule.Name String Rule name.
O365Defender.SafeLinks.Rule.ObjectState String The state of the rule.
O365Defender.SafeLinks.Rule.Priority Number The priority of the rule.
O365Defender.SafeLinks.Rule.RecipientDomainIs Unknown List of domains that are included in the rule.
O365Defender.SafeLinks.Rule.RuleVersion.Build Number Rule build number.
O365Defender.SafeLinks.Rule.RunspaceId String Run space ID.
O365Defender.SafeLinks.Rule.SafeLinksPolicy String The Safe Links policy that’s associated with this Safe Links rule.
O365Defender.SafeLinks.Rule.SentTo Unknown List of recipients included in the rule.
O365Defender.SafeLinks.Rule.SentToMemberOf Unknown List of distribution groups, dynamic distribution groups, or mail-enabled security groups included in the rule.
O365Defender.SafeLinks.Rule.State String The state of the rule.
O365Defender.SafeLinks.Rule.WhenChanged Date The date and time the rule was modified. Time format: YYYY-MM-DDThh:mm:ss+00:00.

Command Example


#### Context Example

```json
{
  "O365Defender.SafeLinks.Rule(obj.Guid === val.Guid)": {
    "Comments": null,
    "Conditions": [
      "Microsoft.Exchange.MessagingPolicies.Rules.Tasks.SentToPredicate"
    ],
    "Description": "If the message:\r\n\tIs sent to 'xsoartest@xsoar.onmicrosoft.com'\r\nTake the following actions:\r\n\tApply safe links policy \"XSOAR Policy\".\r\n",
    "DistinguishedName": "CN=XSOAR Policy,CN=SafeLinksVersioned,CN=Rules,CN=Transport Settings,CN=Configuration,CN=xsoartest.onmicrosoft.com,CN=ConfigurationUnits,DC=EURPR07A123,DC=PROD,DC=OUTLOOK,DC=COM",
    "ExceptIfRecipientDomainIs": null,
    "ExceptIfSentTo": null,
    "ExceptIfSentToMemberOf": null,
    "Exceptions": null,
    "ExchangeVersion": "0.1 (8.0.535.0)",
    "Guid": "e5764de3-5495-4512-93f5-fe96d579fbd9",
    "Identity": "XSOAR Policy",
    "ImmutableId": "e5764de3-5495-4512-93f5-fe96d579fbd9",
    "IsValid": true,
    "Name": "XSOAR Policy",
    "ObjectState": "Unchanged",
    "OrganizationId": "EURPR07A123.PROD.OUTLOOK.COM/Microsoft Exchange Hosted Organizations/xsoartest.onmicrosoft.com - EURPR07A123.PROD.OUTLOOK.COM/ConfigurationUnits/xsoartest.onmicrosoft.com/Configuration",
    "PSComputerName": "outlook.office365.com",
    "PSShowComputerName": false,
    "Priority": 2,
    "RecipientDomainIs": null,
    "RuleVersion": {
      "Build": 0,
      "Major": 14,
      "MajorRevision": 0,
      "Minor": 0,
      "MinorRevision": 0,
      "Revision": 0
    },
    "RunspaceId": "72b57693-0ddb-45b0-a44f-4d722a352635",
    "SafeLinksPolicy": "XSOAR Policy",
    "SentTo": [
      "xsoartest@xsoar.onmicrosoft.com"
    ],
    "SentToMemberOf": null,
    "State": "Enabled",
    "WhenChanged": "2021-10-21T12:49:40+00:00"
  }
}
 

Human Readable Output

Results of o365-defender-safelinks-rule-list

Comments Conditions Description DistinguishedName ExceptIfRecipientDomainIs ExceptIfSentTo ExceptIfSentToMemberOf Exceptions ExchangeVersion Guid Identity ImmutableId IsValid Name ObjectState OrganizationId Priority PSComputerName PSShowComputerName RecipientDomainIs RuleVersion RunspaceId SafeLinksPolicy SentTo SentToMemberOf State WhenChanged
Changed recipients “Microsoft.Exchange.MessagingPolicies.Rules.Tasks.SentToPredicate” If the message: Is sent to ‘xsoartest@xsoar.onmicrosoft.com’\ Take the following actions: Apply safe links policy “XSOAR Policy”.\ CN=XSOAR Policy,CN=SafeLinksVersioned,CN=Rules,CN=Transport Settings,CN=Configuration,CN=xsoartest.onmicrosoft.com,CN=ConfigurationUnits,DC=EURPR07A123,DC=PROD,DC=OUTLOOK,DC=COM         0.1 (8.0.535.0) {“value”:”e5764de3-5495-4512-93f5-fe96d579fbd9”,”Guid”:”e5764de3-5495-4512-93f5-fe96d579fbd9”} XSOAR Policy {“value”:”e5764de3-5495-4512-93f5-fe96d579fbd9”,”Guid”:”e5764de3-5495-4512-93f5-fe96d579fbd9”} true XSOAR Policy Unchanged EURPR07A123.PROD.OUTLOOK.COM/Microsoft Exchange Hosted Organizations/xsoartest.onmicrosoft.com - EURPR07A123.PROD.OUTLOOK.COM/ConfigurationUnits/xsoartest.onmicrosoft.com/Configuration 2 outlook.office365.com false   {“Major”:14,”Minor”:0,”Build”:0,”Revision”:0,”MajorRevision”:0,”MinorRevision”:0} {“value”:”72b57693-0ddb-45b0-a44f-4d722a352635”,”Guid”:”72b57693-0ddb-45b0-a44f-4d722a352635”} XSOAR Policy “xsoartest@xsoar.onmicrosoft.com”   Enabled {“value”:”2021-10-21T12:49:40+00:00”,”DateTime”:”Thursday, October 21, 2021 12:49:40 PM”}

o365-defender-safelinks-rule-create


Create a Safe Links rule in your cloud-based organization.

Base Command

o365-defender-safelinks-rule-create

Input

Argument Name Description Required
name A unique name for the Safe Links rule. Required
safe_links_policy The Safe Links policy to associate with this Safe Links rule. Required
comments An informative comment for the rule, such as what the rule is used for or how it has changed over time. The length of the comment cannot exceed 1024 characters. Optional
enabled Whether the rule is enabled. Possible values are: true, false. Optional
except_if_recipient_domain_is A comma-separated list of exceptions of recipients with email address in the specified domains. Optional
except_if_sent_to A comma-separated list of exceptions of recipients in messages. Optional
except_if_sent_to_member_of A comma-separated list of exceptions of messages sent to members of groups. Optional
priority The priority value for the rule to determines the order of rule processing. A lower integer value indicates a higher priority. The value 0 is the highest priority. Rules cannot have the same priority value. Optional
recipient_domain_is A comma-separated list of recipients with email address in the specified domains. Optional
sent_to A comma-separated list of recipients in messages. You can use any value that uniquely identifies the recipient. Optional
sent_to_member_of A comma-separated list of messages sent to members of distribution groups, dynamic distribution groups, or mail-enabled security groups. You can use any value that uniquely identifies the group. Optional

Context Output

Path Type Description
O365Defender.SafeLinks.Rule.Comments Unknown Informative comments for the rule, such as what the rule is used for or how it has changed over time. The length of the comment cannot exceed 1024 characters.
O365Defender.SafeLinks.Rule.Conditions String The rule condition.
O365Defender.SafeLinks.Rule.Description String The description of the rule.
O365Defender.SafeLinks.Rule.DistinguishedName String Rule distinguished name (DN).
O365Defender.SafeLinks.Rule.ExceptIfRecipientDomainIs Unknown Recipients with an email address in the specified domains are excluded.
O365Defender.SafeLinks.Rule.ExceptIfSentTo Unknown Recipients to be excluded.
O365Defender.SafeLinks.Rule.ExceptIfSentToMemberOf Unknown Recipients in these groups are excluded.
O365Defender.SafeLinks.Rule.Exceptions Unknown Rule exceptions.
O365Defender.SafeLinks.Rule.Guid String The GUID of the rule.
O365Defender.SafeLinks.Rule.Identity String The identity of the Safe Links rule.
O365Defender.SafeLinks.Rule.IsValid Boolean Whether the rule is valid.
O365Defender.SafeLinks.Rule.Name String Rule name.
O365Defender.SafeLinks.Rule.ObjectState String The state of the rule.
O365Defender.SafeLinks.Rule.Priority Number The priority of the rule.
O365Defender.SafeLinks.Rule.RecipientDomainIs Unknown List of domains that are included in the rule.
O365Defender.SafeLinks.Rule.RuleVersion.Build Number Rule build number.
O365Defender.SafeLinks.Rule.RunspaceId String Run space ID.
O365Defender.SafeLinks.Rule.SafeLinksPolicy String The Safe Links policy that’s associated with this Safe Links rule.
O365Defender.SafeLinks.Rule.SentTo Unknown List of recipients included in the rule.
O365Defender.SafeLinks.Rule.SentToMemberOf Unknown List of distribution groups, dynamic distribution groups, or mail-enabled security groups included in the rule.
O365Defender.SafeLinks.Rule.State String The state of the rule.
O365Defender.SafeLinks.Rule.WhenChanged Date The date and time the rule was modified. Time format: YYYY-MM-DDThh:mm:ss+00:00.

Command Example

!o365-defender-safelinks-rule-create name="xsoartest rule" safe_links_policy="xsoartest policy" enabled=true sent_to=xsoartest@xsoar.onmicrosoft.com

Context Example

{
  "O365Defender.SafeLinks.Rule(obj.Guid === val.Guid)": {
    "Comments": null,
    "Conditions": [
      "Microsoft.Exchange.MessagingPolicies.Rules.Tasks.SentToPredicate"
    ],
    "Description": "If the message:\r\n\tIs sent to 'xsoartest@xsoar.onmicrosoft.com'\r\nTake the following actions:\r\n\tApply safe links policy \"xsoartest policy"\".\r\n",
    "DistinguishedName": "CN=xsoartest rule,CN=SafeLinksVersioned,CN=Rules,CN=Transport Settings,CN=Configuration,CN=xsoartest.onmicrosoft.com,CN=ConfigurationUnits,DC=EURPR07A123,DC=PROD,DC=OUTLOOK,DC=COM",
    "ExceptIfRecipientDomainIs": null,
    "ExceptIfSentTo": null,
    "ExceptIfSentToMemberOf": null,
    "Exceptions": null,
    "ExchangeVersion": "0.1 (8.0.535.0)",
    "Guid": "e5764de3-5495-4512-93f5-fe96d579fbd9",
    "Identity": "XSOAR Policy",
    "ImmutableId": "e5764de3-5495-4512-93f5-fe96d579fbd9",
    "IsValid": true,
    "Name": "XSOAR Policy",
    "ObjectState": "Unchanged",
    "OrganizationId": "EURPR07A123.PROD.OUTLOOK.COM/Microsoft Exchange Hosted Organizations/xsoartest.onmicrosoft.com - EURPR07A123.PROD.OUTLOOK.COM/ConfigurationUnits/xsoartest.onmicrosoft.com/Configuration",
    "PSComputerName": "outlook.office365.com",
    "PSShowComputerName": false,
    "Priority": 2,
    "RecipientDomainIs": null,
    "RuleVersion": {
      "Build": 0,
      "Major": 14,
      "MajorRevision": 0,
      "Minor": 0,
      "MinorRevision": 0,
      "Revision": 0
    },
    "RunspaceId": "72b57693-0ddb-45b0-a44f-4d722a352635",
    "SafeLinksPolicy": "xsoartest policy",
    "SentTo": [
      "xsoartest@xsoar.onmicrosoft.com"
    ],
    "SentToMemberOf": null,
    "State": "Enabled",
    "WhenChanged": "2021-10-21T12:49:40+00:00"
  }
}
 

Human Readable Output

Results of o365-defender-safelinks-rule-create

Comments Conditions Description DistinguishedName ExceptIfRecipientDomainIs ExceptIfSentTo ExceptIfSentToMemberOf Exceptions ExchangeVersion Guid Identity ImmutableId IsValid Name ObjectState OrganizationId Priority PSComputerName PSShowComputerName RecipientDomainIs RuleVersion RunspaceId SafeLinksPolicy SentTo SentToMemberOf State WhenChanged
Changed recipients “Microsoft.Exchange.MessagingPolicies.Rules.Tasks.SentToPredicate” If the message: Is sent to ‘xsoartest@xsoar.onmicrosoft.com’\ Take the following actions: Apply safe links policy “XSOAR Policy”.\ CN=XSOAR Policy,CN=SafeLinksVersioned,CN=Rules,CN=Transport Settings,CN=Configuration,CN=xsoartest.onmicrosoft.com,CN=ConfigurationUnits,DC=EURPR07A123,DC=PROD,DC=OUTLOOK,DC=COM         0.1 (8.0.535.0) {“value”:”e5764de3-5495-4512-93f5-fe96d579fbd9”,”Guid”:”e5764de3-5495-4512-93f5-fe96d579fbd9”} XSOAR Policy {“value”:”e5764de3-5495-4512-93f5-fe96d579fbd9”,”Guid”:”e5764de3-5495-4512-93f5-fe96d579fbd9”} true XSOAR Policy Unchanged EURPR07A123.PROD.OUTLOOK.COM/Microsoft Exchange Hosted Organizations/xsoartest.onmicrosoft.com - EURPR07A123.PROD.OUTLOOK.COM/ConfigurationUnits/xsoartest.onmicrosoft.com/Configuration 2 outlook.office365.com false   {“Major”:14,”Minor”:0,”Build”:0,”Revision”:0,”MajorRevision”:0,”MinorRevision”:0} {“value”:”72b57693-0ddb-45b0-a44f-4d722a352635”,”Guid”:”72b57693-0ddb-45b0-a44f-4d722a352635”} XSOAR Policy “xsoartest@xsoar.onmicrosoft.com”   Enabled {“value”:”2021-10-21T12:49:40+00:00”,”DateTime”:”Thursday, October 21, 2021 12:49:40 PM”}

o365-defender-safelinks-rule-update


Update a given Safe Links rule.

Base Command

o365-defender-safelinks-rule-update

Input

Argument Name Description Required
name A unique name for the Safe Links rule. Required
safe_links_policy The Safe Links policy to associate with this Safe Links rule. Required
comments An informative comment for the rule, such as what the rule is used for or how it has changed over time. The length of the comment cannot exceed 1024 characters. Optional
enabled Whether the rule is enabled. Possible values are: true, false. Optional
except_if_recipient_domain_is A comma-separated list of exceptions of recipients with an email address in the specified domains. Optional
except_if_sent_to A comma-separated list of exceptions of recipients in messages. Optional
except_if_sent_to_member_of A comma-separated list of exceptions of messages sent to members of groups. Optional
priority The priority value for the rule to determines the order of rule processing. A lower integer value indicates a higher priority. The value 0 is the highest priority. Rules cannot have the same priority value. Optional
recipient_domain_is A comma-separated list of recipients with an email address in the specified domains. Optional
sent_to A comma-separated list of recipients in messages. You can use any value that uniquely identifies the recipient. Optional
sent_to_member_of A comma-separated list of messages sent to members of distribution groups, dynamic distribution groups, or mail-enabled security groups. You can use any value that uniquely identifies the group. Optional

Context Output

Path Type Description
O365Defender.SafeLinks.Rule.Comments Unknown Informative comments for the rule, such as what the rule is used for or how it has changed over time. The length of the comment cannot exceed 1024 characters.
O365Defender.SafeLinks.Rule.Conditions String The rule condition.
O365Defender.SafeLinks.Rule.Description String The description of the rule.
O365Defender.SafeLinks.Rule.DistinguishedName String Rule distinguished name (DN).
O365Defender.SafeLinks.Rule.ExceptIfRecipientDomainIs Unknown Recipients with email address in the specified domains are excluded.
O365Defender.SafeLinks.Rule.ExceptIfSentTo Unknown Recipients to be excluded.
O365Defender.SafeLinks.Rule.ExceptIfSentToMemberOf Unknown Recipients in these groups are excluded.
O365Defender.SafeLinks.Rule.Exceptions Unknown Rule exceptions.
O365Defender.SafeLinks.Rule.Guid String The GUID of the rule.
O365Defender.SafeLinks.Rule.Identity String The identity of the Safe Links rule.
O365Defender.SafeLinks.Rule.IsValid Boolean Whether the rule is valid.
O365Defender.SafeLinks.Rule.Name String Rule name.
O365Defender.SafeLinks.Rule.ObjectState String The state of the rule.
O365Defender.SafeLinks.Rule.Priority Number The priority of the rule.
O365Defender.SafeLinks.Rule.RecipientDomainIs Unknown List of domains that are included in the rule.
O365Defender.SafeLinks.Rule.RuleVersion.Build Number Rule build number.
O365Defender.SafeLinks.Rule.RunspaceId String Run space ID.
O365Defender.SafeLinks.Rule.SafeLinksPolicy String The Safe Links policy that’s associated with this Safe Links rule.
O365Defender.SafeLinks.Rule.SentTo Unknown List of recipients included in the rule.
O365Defender.SafeLinks.Rule.SentToMemberOf Unknown List of distribution groups, dynamic distribution groups, or mail-enabled security groups included in the rule.
O365Defender.SafeLinks.Rule.State String The state of the rule.
O365Defender.SafeLinks.Rule.WhenChanged Date The date and time the rule was modified. Time format: YYYY-MM-DDThh:mm:ss+00:00.

Command Example

!o365-defender-safelinks-rule-update name=XSOAR Rule safe_links_policy=XSOAR Policy comments="Description of the updated rule"

Context Example

{
  "O365Defender.SafeLinks.Rule(obj.Guid === val.Guid)": {
    "Comments": "Description of the updated rule",
    "Conditions": [
      "Microsoft.Exchange.MessagingPolicies.Rules.Tasks.SentToPredicate"
    ],
    "Description": "If the message:\r\n\tIs sent to 'xsoartest@xsoar.onmicrosoft.com'\r\nTake the following actions:\r\n\tApply safe links policy \"XSOAR Policy\".\r\n",
    "DistinguishedName": "CN=XSOAR Policy,CN=SafeLinksVersioned,CN=Rules,CN=Transport Settings,CN=Configuration,CN=xsoartest.onmicrosoft.com,CN=ConfigurationUnits,DC=EURPR07A123,DC=PROD,DC=OUTLOOK,DC=COM",
    "ExceptIfRecipientDomainIs": null,
    "ExceptIfSentTo": null,
    "ExceptIfSentToMemberOf": null,
    "Exceptions": null,
    "ExchangeVersion": "0.1 (8.0.535.0)",
    "Guid": "e5764de3-5495-4512-93f5-fe96d579fbd9",
    "Identity": "XSOAR Policy",
    "ImmutableId": "e5764de3-5495-4512-93f5-fe96d579fbd9",
    "IsValid": true,
    "Name": "XSOAR Rule",
    "ObjectState": "Unchanged",
    "OrganizationId": "EURPR07A123.PROD.OUTLOOK.COM/Microsoft Exchange Hosted Organizations/xsoartest.onmicrosoft.com - EURPR07A123.PROD.OUTLOOK.COM/ConfigurationUnits/xsoartest.onmicrosoft.com/Configuration",
    "PSComputerName": "outlook.office365.com",
    "PSShowComputerName": false,
    "Priority": 2,
    "RecipientDomainIs": null,
    "RuleVersion": {
      "Build": 0,
      "Major": 14,
      "MajorRevision": 0,
      "Minor": 0,
      "MinorRevision": 0,
      "Revision": 0
    },
    "RunspaceId": "72b57693-0ddb-45b0-a44f-4d722a352635",
    "SafeLinksPolicy": "XSOAR Policy",
    "SentTo": [
      "xsoartest@xsoar.onmicrosoft.com"
    ],
    "SentToMemberOf": null,
    "State": "Enabled",
    "WhenChanged": "2021-10-21T12:49:40+00:00"
  }
}
 

Human Readable Output

Results of o365-defender-safelinks-rule-update

Comments Conditions Description DistinguishedName ExceptIfRecipientDomainIs ExceptIfSentTo ExceptIfSentToMemberOf Exceptions ExchangeVersion Guid Identity ImmutableId IsValid Name ObjectState OrganizationId Priority PSComputerName PSShowComputerName RecipientDomainIs RuleVersion RunspaceId SafeLinksPolicy SentTo SentToMemberOf State WhenChanged
Changed recipients “Microsoft.Exchange.MessagingPolicies.Rules.Tasks.SentToPredicate” If the message: Is sent to ‘xsoartest@xsoar.onmicrosoft.com’\ Take the following actions: Apply safe links policy “XSOAR Policy”.\ CN=XSOAR Policy,CN=SafeLinksVersioned,CN=Rules,CN=Transport Settings,CN=Configuration,CN=xsoartest.onmicrosoft.com,CN=ConfigurationUnits,DC=EURPR07A123,DC=PROD,DC=OUTLOOK,DC=COM         0.1 (8.0.535.0) {“value”:”e5764de3-5495-4512-93f5-fe96d579fbd9”,”Guid”:”e5764de3-5495-4512-93f5-fe96d579fbd9”} XSOAR Policy {“value”:”e5764de3-5495-4512-93f5-fe96d579fbd9”,”Guid”:”e5764de3-5495-4512-93f5-fe96d579fbd9”} true XSOAR Policy Unchanged EURPR07A123.PROD.OUTLOOK.COM/Microsoft Exchange Hosted Organizations/xsoartest.onmicrosoft.com - EURPR07A123.PROD.OUTLOOK.COM/ConfigurationUnits/xsoartest.onmicrosoft.com/Configuration 2 outlook.office365.com false   {“Major”:14,”Minor”:0,”Build”:0,”Revision”:0,”MajorRevision”:0,”MinorRevision”:0} {“value”:”72b57693-0ddb-45b0-a44f-4d722a352635”,”Guid”:”72b57693-0ddb-45b0-a44f-4d722a352635”} XSOAR Policy “xsoartest@xsoar.onmicrosoft.com”   Enabled {“value”:”2021-10-21T12:49:40+00:00”,”DateTime”:”Thursday, October 21, 2021 12:49:40 PM”}

o365-defender-safelinks-detailed-report-get


Get detailed information about Safe Links results for the last 7 days. Yesterday is the most recent date that you can specify.

Base Command

o365-defender-safelinks-detailed-report-get

Input

Argument Name Description Required
start_date Start date of the date range in MM-DD-YYYY format.Yesterday is the most recent date that you can specify. You can’t specify a date that’s older than 7 days. Possible values are: . Required
end_date End date of the date range in MM-DD-YYYY format.Yesterday is the most recent date that you can specify. You can’t specify a date that’s older than 7 days. Possible values are: . Required
domain filters the results by the domain in the URL. Possible values are: . Optional
app_names filters the results by the app where the link was found. You can enter multiple values separated by commas e.g “Value1,Value2,…ValueN”. Possible values are: Email Client, OfficeDocs, Teams. Optional
action filters the results by action. You can enter multiple values separated by commas e.g Value1,Value2,…ValueN. Possible values are: Allowed, Blocked, ClickedDuringScan, ClickedEvenBlocked, Scanning, TenantAllowed, TenantBlocked, TenantBlockedAndClickedThrough. Optional
recipient_address filters the results by the recipient’s email address. Possible values are: . Optional
page Page number of the results you want to view. Valid input for this parameter is an integer between 1 and 1000. The default value is 1. Possible values are: . Optional
page_size Specifies the maximum number of entries per page. Valid input for this parameter is an integer between 1 and 5000. The default value is 1000. Possible values are: . Optional

Context Output

Path Type Description
O365Defender.SafeLinks.DetailedReport.Data.ClickTime Date Time the url was clicked.
O365Defender.SafeLinks.DetailedReport.Data.InternalMessageId String Internal message id.
O365Defender.SafeLinks.DetailedReport.Data.ClientMessageId String Client message id.
O365Defender.SafeLinks.DetailedReport.Data.SenderAddress String Sender of the email with the clicked URL.
O365Defender.SafeLinks.DetailedReport.Data.RecipientAddress String Receiver of the email with the clicked URL.
O365Defender.SafeLinks.DetailedReport.Data.Url String Clicked URL.
O365Defender.SafeLinks.DetailedReport.Data.UrlDomain String Domain of th clicked URL.
O365Defender.SafeLinks.DetailedReport.Data.Action String Action type.
O365Defender.SafeLinks.DetailedReport.Data.AppName String App where the link was found.
O365Defender.SafeLinks.DetailedReport.Data.SourceId Unknown Source id.
O365Defender.SafeLinks.DetailedReport.Data.Organization String Organization.
O365Defender.SafeLinks.DetailedReport.Data.DetectedBy Unknown  
O365Defender.SafeLinks.DetailedReport.Data.UrlType Unknown  
O365Defender.SafeLinks.DetailedReport.Data.Flags Number 0: Allowed 1: Blocked 2: ClickedEvenBlocked 3: ClickedDuringScan
O365Defender.SafeLinks.DetailedReport.ReportId Number The report id, unique for every run

Command example

!o365-defender-safelinks-detailed-report-get end_date=08-01-2022 start_date=07-31-2022

Context Example

{
    "O365Defender": {
        "SafeLinks": {
            "DetailedReport": {
                "Data": [
                    {
                        "Action": "Allowed",
                        "AppName": "Email Client",
                        "ClickTime": "2022-08-01T10:12:49",
                        "ClientMessageId": null,
                        "DetectedBy": "ATP safe links",
                        "EndDate": "0001-01-01T00:00:00",
                        "Flags": 0,
                        "InternalMessageId": "dc6ebe31-e968-4cf8-a4b4-08da73a65b1c",
                        "Organization": "test.onmicrosoft.com",
                        "PSComputerName": "outlook.office365.com",
                        "PSShowComputerName": false,
                        "RecipientAddress": "test@test.onmicrosoft.com",
                        "RunspaceId": "93d2c78c-db42-41a0-b67c-5f72881b7338",
                        "SenderAddress": null,
                        "SourceId": null,
                        "StartDate": "0001-01-01T00:00:00",
                        "Url": "http://go.microsoft.com/",
                        "UrlDomain": "go.microsoft.com",
                        "UrlType": ""
                    }
                ],
                "ReportId": "93d2c78c-db42-41a0-b67c-5f72881b7338"
            }
        }
    }
}

Human Readable Output

Results of o365-defender-safelinks-detailed-report-get

Action AppName ClickTime ClientMessageId DetectedBy EndDate Flags InternalMessageId Organization PSComputerName PSShowComputerName RecipientAddress RunspaceId SenderAddress SourceId StartDate Url UrlDomain UrlType
Allowed Email Client {“value”:”2022-08-01T10:12:49”,”DateTime”:”Monday, August 1, 2022 10:12:49 AM”}   ATP safe links {“value”:”0001-01-01T00:00:00”,”DateTime”:”Monday, January 1, 0001 12:00:00 AM”} 0 {“value”:”dc6ebe31-e968-4cf8-a4b4-08da73a65b1c”,”Guid”:”dc6ebe31-e968-4cf8-a4b4-08da73a65b1c”} test.onmicrosoft.com outlook.office365.com false test@test.onmicrosoft.com {“value”:”39cbdab4-5b97-4f20-bb17-b0d1848183a6”,”Guid”:”39cbdab4-5b97-4f20-bb17-b0d1848183a6”}     {“value”:”0001-01-01T00:00:00”,”DateTime”:”Monday, January 1, 0001 12:00:00 AM”} http://go.microsoft.com/ go.microsoft.com  

o365-defender-safelinks-aggregate-report-get


general information about Safe Links results for the last 90 days. Yesterday is the most recent date that you can specify.

Base Command

o365-defender-safelinks-aggregate-report-get

Input

Argument Name Description Required
start_date Start date of the date range in MM-DD-YYYY format.Yesterday is the most recent date that you can specify. You can’t specify a date that’s older than 90 days. Possible values are: . Required
end_date End date of the date range in MM-DD-YYYY format.YYesterday is the most recent date that you can specify. You can’t specify a date that’s older than 90 days. Possible values are: . Required
app_names filters the results by the app where the link was found. You can enter multiple values separated by commas e.g “Value1,Value2,…ValueN”. Possible values are: Email Client, OfficeDocs, Teams. Optional
action filters the results by action. You can enter multiple values separated by commas e.g Value1,Value2,…ValueN. Possible values are: Allowed, Blocked, ClickedDuringScan, ClickedEvenBlocked, Scanning, TenantAllowed, TenantBlocked, TenantBlockedAndClickedThrough. Optional
summerize_by Returns totals based on the values you specify. Summarizing reduces the amount of data that’s retrieved for the report, and delivers the report faster. By default the summrize is by Action. Possible values are: Action, App. Optional

Context Output

Path Type Description
O365Defender.SafeLinks.AggregateReport.Data.App String App where the link was found.
O365Defender.SafeLinks.AggregateReport.Data.Action String Action type.
O365Defender.SafeLinks.AggregateReport.Data.MessageCount Number Number of messages with a link.
O365Defender.SafeLinks.AggregateReport.Data.RecipientCount Number Number of recipients of the link.
O365Defender.SafeLinks.AggregateReport.ReportId Number The report id, unique for every run

Command example

!o365-defender-safelinks-aggregate-report-get end_date=08-01-2022 start_date=07-31-2022

Context Example

{
    "O365Defender": {
        "SafeLinks": {
            "AggregateReport": {
                "Data": [
                    {
                        "Action": "Allowed",
                        "App": "",
                        "EndDate": "0001-01-01T00:00:00",
                        "MessageCount": 0,
                        "PSComputerName": "outlook.office365.com",
                        "PSShowComputerName": false,
                        "RecipientCount": 0,
                        "RunspaceId": "e3633f6c-e9b5-4c9d-9acc-8f669b28a974",
                        "StartDate": "0001-01-01T00:00:00"
                    },
                    {
                        "Action": "TenantAllowed",
                        "App": "",
                        "EndDate": "0001-01-01T00:00:00",
                        "MessageCount": 0,
                        "PSComputerName": "outlook.office365.com",
                        "PSShowComputerName": false,
                        "RecipientCount": 0,
                        "RunspaceId": "e3633f6c-e9b5-4c9d-9acc-8f669b28a974",
                        "StartDate": "0001-01-01T00:00:00"
                    },
                    {
                        "Action": "Blocked",
                        "App": "",
                        "EndDate": "0001-01-01T00:00:00",
                        "MessageCount": 0,
                        "PSComputerName": "outlook.office365.com",
                        "PSShowComputerName": false,
                        "RecipientCount": 0,
                        "RunspaceId": "e3633f6c-e9b5-4c9d-9acc-8f669b28a974",
                        "StartDate": "0001-01-01T00:00:00"
                    },
                    {
                        "Action": "TenantBlocked",
                        "App": "",
                        "EndDate": "0001-01-01T00:00:00",
                        "MessageCount": 0,
                        "PSComputerName": "outlook.office365.com",
                        "PSShowComputerName": false,
                        "RecipientCount": 0,
                        "RunspaceId": "e3633f6c-e9b5-4c9d-9acc-8f669b28a974",
                        "StartDate": "0001-01-01T00:00:00"
                    },
                    {
                        "Action": "ClickedEvenBlocked",
                        "App": "",
                        "EndDate": "0001-01-01T00:00:00",
                        "MessageCount": 0,
                        "PSComputerName": "outlook.office365.com",
                        "PSShowComputerName": false,
                        "RecipientCount": 0,
                        "RunspaceId": "e3633f6c-e9b5-4c9d-9acc-8f669b28a974",
                        "StartDate": "0001-01-01T00:00:00"
                    },
                    {
                        "Action": "TenantBlockedAndClickedThrough",
                        "App": "",
                        "EndDate": "0001-01-01T00:00:00",
                        "MessageCount": 0,
                        "PSComputerName": "outlook.office365.com",
                        "PSShowComputerName": false,
                        "RecipientCount": 0,
                        "RunspaceId": "e3633f6c-e9b5-4c9d-9acc-8f669b28a974",
                        "StartDate": "0001-01-01T00:00:00"
                    },
                    {
                        "Action": "Scanning",
                        "App": "",
                        "EndDate": "0001-01-01T00:00:00",
                        "MessageCount": 0,
                        "PSComputerName": "outlook.office365.com",
                        "PSShowComputerName": false,
                        "RecipientCount": 0,
                        "RunspaceId": "e3633f6c-e9b5-4c9d-9acc-8f669b28a974",
                        "StartDate": "0001-01-01T00:00:00"
                    },
                    {
                        "Action": "ClickedDuringScan",
                        "App": "",
                        "EndDate": "0001-01-01T00:00:00",
                        "MessageCount": 0,
                        "PSComputerName": "outlook.office365.com",
                        "PSShowComputerName": false,
                        "RecipientCount": 0,
                        "RunspaceId": "e3633f6c-e9b5-4c9d-9acc-8f669b28a974",
                        "StartDate": "0001-01-01T00:00:00"
                    }
                ],
                "ReportId": "e3633f6c-e9b5-4c9d-9acc-8f669b28a974"
            }
        }
    }
}

Human Readable Output

Results of o365-defender-safelinks-aggregate-report-get

Action App EndDate MessageCount PSComputerName PSShowComputerName RecipientCount RunspaceId StartDate
Allowed   {“value”:”0001-01-01T00:00:00”,”DateTime”:”Monday, January 1, 0001 12:00:00 AM”} 0 outlook.office365.com false 0 {“value”:”0063bc64-9230-43a9-91b3-10829ec2801f”,”Guid”:”0063bc64-9230-43a9-91b3-10829ec2801f”} {“value”:”0001-01-01T00:00:00”,”DateTime”:”Monday, January 1, 0001 12:00:00 AM”}

Known Limitations

  • Safe Links does not work on mail-enabled public folders.
  • Safe Links protection is available in the following locations:
    • Office 365 apps: Safe Links protection for Office 365 apps is available in supported desktop, mobile, and web apps. You configure Safe Links protection for Office 365 apps in the global setting that are outside of Safe Links policies. For instructions, see Configure global settings for Safe Links settings in Microsoft Defender for Office 365.
    • Microsoft Teams: Safe Links protection for links in Teams conversations, group chats, or from channels is also controlled by Safe Links policies. There is no default Safe Links policy, so to get the protection of Safe Links in Teams, you need to create one or more Safe Links policies.
    • Email messages: Safe Links protection for links in email messages is controlled by Safe Links policies. There is no default Safe Links policy, so to get the protection of Safe Links in email messages, you need to create one or more Safe Links policies.
  • Allow up to 30 minutes for a new or updated policy to be applied.
  • When using the o365-defender-safelinks-detail-report-get command, note the following:
    • The date range can’t be more than seven days.
    • Yesterday is the most recent date that you can specify.
    • The start date can’t be older than 10 days from today.

Configuration parameters

  • url — Exchange Online URL (required)
  • credentials — Email / User Principal Name (Required)
  • insecure — Trust any certificate (not secure)

Commands (13)

  • o365-defender-safelinks-aggregate-report-get

    general information about Safe Links results for the last 90 days. Yesterday is the most recent date that you can specify.

  • o365-defender-safelinks-auth-complete

    Completes the OAuth2.0 authorization process.

  • o365-defender-safelinks-auth-start

    Starts the OAuth2.0 authorization process.

  • o365-defender-safelinks-auth-test

    Tests the OAuth2.0 authorization process.

  • o365-defender-safelinks-detail-report-get Deprecated

    Deprecated, use o365-defender-safelinks-detailed-report-get instead. Gets detailed information about Safe Links results for the last 7 days. Yesterday is the most recent date you can specify. Currently, the date range can't be more than seven days.

  • o365-defender-safelinks-detailed-report-get

    Get detailed information about Safe Links results for the last 7 days. Yesterday is the most recent date that you can specify.

  • o365-defender-safelinks-policy-create

    Create a new Safe Links policy.

  • o365-defender-safelinks-policy-list

    List the Safe Links policies in your cloud-based organization.

  • o365-defender-safelinks-policy-remove

    Remove a Safe Links policy.

  • o365-defender-safelinks-policy-update

    Update a Safe Links policy.

  • o365-defender-safelinks-rule-create

    Create a Safe Links rule in your cloud-based organization.

  • o365-defender-safelinks-rule-list

    List Safe Links rules in your cloud-based organization.

  • o365-defender-safelinks-rule-update

    Update a given Safe Links rule.


$COMMAND_PREFIX = "o365-defender-safelinks"
$INTEGRATION_ENTRY_CONTEXT = "O365Defender.SafeLinks"

function CreateContextForReport{
    Param(
        $raw_response
    )
    $context_data = @{"Data"=$raw_response}
    if ($raw_response -is [array]) {
        # RunSapceId is the same for all items in data.
        $context_data.ReportId=$raw_response[0].RunspaceId
    }

    else {
        $context_data.ReportId=$raw_response.RunspaceId
    }

    return $context_data
}
<#
    .DESCRIPTION
    Create context data for report commands. Where the context is divided to "Data" and "ReportId"

    .PARAMETER arg_value
    The raw value of the response.

    .EXAMPLE
    CreateContextForReport {field="data_1";RunspaceId="1"} -> {"Data"={field="data_1";RunspaceId="1"};
                                                               "ReportId" = "1"}
    #>
function EncloseArgWithQuotes {
    Param (
        [string]$arg_value
    )
    if (!($arg_value)) {
        return ""
    }

    $arrayed_value = $arg_value -split ","
    if ($arrayed_value.Length -eq 1) {
        return $arrayed_value
    }
    for ($i = 0; $i -lt $arrayed_value.Count; $i++) {
        $temp_val = $arrayed_value[$i]
        if ($temp_val[0] -ne '"') {
            $arrayed_value[$i] = '"' + $arrayed_value[$i].Trim() + '"'
        }
    }

    $return_value = $arrayed_value -join ","

    return $return_value

    <#
    .DESCRIPTION
    Encloses the value of an argument with double quotes and trim it. In the case it's a CSV value
    it will do that for every value in the list.

    .PARAMETER arg_value
    The raw value of the argument.

    .EXAMPLE
    EncloseArgWithQuotes("a,b,c") -> "a","b","c"
    EncloseArgWithQuotes("a, b,c ") -> "a","b","c"
    EncloseArgWithQuotes("\"a\",b,c") -> "a","b","c"
    EncloseArgWithQuotes("") -> ""
    EncloseArgWithQuotes -> ""
    #>
}

function UpdateIntegrationContext([OAuth2DeviceCodeClient]$client){
    $integration_context = @{
        "DeviceCode" = $client.device_code
        "DeviceCodeExpiresIn" = $client.device_code_expires_in
        "DeviceCodeCreationTime" = $client.device_code_creation_time
        "AccessToken" = $client.access_token
        "RefreshToken" = $client.refresh_token
        "AccessTokenExpiresIn" = $client.access_token_expires_in
        "AccessTokenCreationTime" = $client.access_token_creation_time
    }

    SetIntegrationContext $integration_context
    <#
        .DESCRIPTION
        Update integration context from OAuth2DeviceCodeClient client

        .EXAMPLE
        UpdateIntegrationContext $client

        .PARAMETER search_name
        OAuth2DeviceCodeClient client.
    #>
}

function CreateNewSession {
    [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingConvertToSecureStringWithPlainText', '', Scope='Function')]
    [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingPlainTextForPassword', '', Scope='Function')]
    [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSReviewUnusedParameter', '', Scope='Function')]
    param([string]$url, [string]$upn, [string]$password, [string]$bearer_token, [bool]$insecure, [bool]$proxy)
    if ($password){
        $url = "$url/powershell-liveid"
    }
    else
    {
        $url = "$url/powershell-liveid?BasicAuthToOAuthConversion=true"
    }

    if ($password){
        $credential = ConvertTo-SecureString "$password" -AsPlainText -Force
    } else {
        $credential = ConvertTo-SecureString "Bearer $bearer_token" -AsPlainText -Force
    }
    $credential = New-Object System.Management.Automation.PSCredential($upn, $credential)
    $session_option_params = @{
        "SkipCACheck" = $insecure
        "SkipCNCheck" = $insecure
    }
    $session_options =  New-PSSessionOption @session_option_params
    $sessions_params = @{
        "ConfigurationName" = "Microsoft.Exchange"
        "ConnectionUri" = $url
        "Credential" = $credential
        "Authentication" = "Basic"
        "AllowRedirection" = $true
        "SessionOption" = $session_options
    }
    $session = New-PSSession @sessions_params -WarningAction:SilentlyContinue

    if (!$session) {
        throw "Fail - establishing session to $url"
    }

    return $session
    <#
        .DESCRIPTION
        Creates new PSSession using Oauth2.0 method.

        .PARAMETER url
        Exchange Online url.

        .PARAMETER upn
        User Principal Name (UPN) is the name of a system user in an email address format.

        .PARAMETER password
        Password is filled only if authentication method is basic auth.

        .PARAMETER bearer_token
        Valid bearer token value.

        .EXAMPLE proxy
        Wheter to user system proxy configuration or not.

        .PARAMETER insecure
        Wheter to trust any TLS/SSL Certificate) or not.


        .EXAMPLE
        CreateNewSession("outlook.com", "user@microsoft.com", "dfhsdkjhkjhvkdvbihsgiu")

        .OUTPUTS
        PSSession - PSSession object.

        .LINK
        https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/new-pssession?view=powershell-7
        https://docs.microsoft.com/en-us/powershell/partnercenter/multi-factor-auth?view=partnercenterps-3.0#exchange-online-powershell
    #>
}

class OAuth2DeviceCodeClient {
    [string]$application_id = "a0c73c16-a7e3-4564-9a95-2bdf47383716"
    [string]$application_scope = "offline_access%20https%3A//outlook.office365.com/.default"
    [string]$device_code
    [int]$device_code_expires_in
    [int]$device_code_creation_time
    [string]$access_token
    [string]$refresh_token
    [int]$access_token_expires_in
    [int]$access_token_creation_time
    [bool]$insecure
    [bool]$proxy

    OAuth2DeviceCodeClient(
            [string]$device_code, [string]$device_code_expires_in, [string]$device_code_creation_time, [string]$access_token,
            [string]$refresh_token,[string]$access_token_expires_in, [string]$access_token_creation_time, [bool]$insecure, [bool]$proxy
    ) {
        $this.device_code = $device_code
        $this.device_code_expires_in = $device_code_expires_in
        $this.device_code_creation_time = $device_code_creation_time
        $this.access_token = $access_token
        $this.refresh_token = $refresh_token
        $this.access_token_expires_in = $access_token_expires_in
        $this.access_token_creation_time = $access_token_creation_time
        $this.insecure = $insecure
        $this.proxy = $proxy
        <#
            .DESCRIPTION
            OAuth2DeviceCodeClient manage state of OAuth2.0 device-code flow described in https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-device-code.

            .DESCRIPTION
            Its not recommended to create an object using the constructor, Use static method CreateClientFromIntegrationContext() instead.

            OAuth2DeviceCodeClient states are:
                1. Getting device-code (Will be used in stage 2) and user-code (Will be used by the user to authorize permissions) from Microsoft application.
                2. Getting access-token and refresh-token - after use authorize (Using stage 1 - device code)
                3. Refresh access-token if access-token is expired.

            .PARAMETER device_code
            A long string used to verify the session between the client and the authorization server.
            The client uses this parameter to request the access token from the authorization server.

            .PARAMETER device_code_expires_in
            The number of seconds before the device_code and user_code expire. (15 minutes)

            .PARAMETER access_token
            Opaque string, Issued for the scopes that were requested.

            .PARAMETER refresh_token
            Opaque string, Issued if the original scope parameter included offline_access. (Valid for 90 days)

            .PARAMETER access_token_expires_in
            Number of seconds before the included access token is valid for. (Usually - 60 minutes)

            .PARAMETER access_token_creation_time
            Unix time of access token creation (Used for knowing when to refresh the token).

            .PARAMETER access_token_expires_in
            Number of seconds before the included access token is valid for. (Usually - 60 minutes)

            .PARAMETER insecure
            Whether to trust any TLS/SSL Certificate) or not.

            .PARAMETER proxy
            Whether to user system proxy configuration or not.

            .NOTES
            1. Application id - a0c73c16-a7e3-4564-9a95-2bdf47383716 , This is well-known application publicly managed by Microsoft and will not work in on-premise environment.

            .LINK
            https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-device-code
        #>
    }

    static [OAuth2DeviceCodeClient]CreateClientFromIntegrationContext([bool]$insecure, [bool]$proxy){
        $ic = GetIntegrationContext
        $client = [OAuth2DeviceCodeClient]::new(
                $ic.DeviceCode, $ic.DeviceCodeExpiresIn, $ic.DeviceCodeCreationTime, $ic.AccessToken, $ic.RefreshToken,
                $ic.AccessTokenExpiresIn, $ic.AccessTokenCreationTime, $insecure, $proxy
        )

        return $client
        <#
            .DESCRIPTION
            Static method which create object (factory method) from populated values in integration context.

            .EXAMPLE
            [OAuth2DeviceCodeClient]::CreateClientFromIntegrationContext()

            .OUTPUTS
            OAuth2DeviceCodeClient initialized object.
        #>
    }

    [PSObject]AuthorizationRequest() {
        # Reset object-properties
        $this.device_code = $null
        $this.device_code_expires_in = $null
        $this.device_code_creation_time = $null
        # Get device-code and user-code
        $params = @{
            "URI" = "https://login.microsoftonline.com/organizations/oauth2/v2.0/devicecode"
            "Method" = "Post"
            "Headers" = (New-Object "System.Collections.Generic.Dictionary[[String],[String]]").Add("Content-Type", "application/x-www-form-urlencoded")
            "Body" = "client_id=$($this.application_id)&scope=$($this.application_scope)"
            "NoProxy" = !$this.proxy
            "SkipCertificateCheck" = $this.insecure
        }
        $response = Invoke-WebRequest @params
        $response_body = ConvertFrom-Json $response.Content
        # Update object properties
        $this.device_code = $response_body.device_code
        $this.device_code_creation_time = [int][double]::Parse((Get-Date -UFormat %s))
        $this.device_code_expires_in = [int]::Parse($response_body.expires_in)

        return $response_body

        <#
            .DESCRIPTION
            Reset values populated in instance context and getting new device-code and user-code.

            .EXAMPLE
            $client.AuthorizationRequest()

            .OUTPUTS
            psobject - Raw body response.

            .LINK
            https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-device-code#device-authorization-request
        #>
    }

    [psobject]AccessTokenRequest() {
        # Get new token using device-code
        try {
            $params = @{
                "URI" = "https://login.microsoftonline.com/organizations/oauth2/v2.0/token"
                "Method" = "Post"
                "Headers" = (New-Object "System.Collections.Generic.Dictionary[[String],[String]]").Add("Content-Type", "application/x-www-form-urlencoded")
                "Body" = "grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Adevice_code&code=$($this.device_code)&client_id=$($this.application_id)"
                "NoProxy" = !$this.proxy
                "SkipCertificateCheck" = $this.insecure
            }
            $response = Invoke-WebRequest @params
            $response_body = ConvertFrom-Json $response.Content
        }
        catch {
            $response_body = ConvertFrom-Json $_.ErrorDetails.Message
            if ($response_body.error -eq "authorization_pending" -or $response_body.error -eq "invalid_grant") {
                $error_details = "Please run command !$script:COMMAND_PREFIX-auth-start , before running this command."
            }
            elseif ($response_body.error -eq "expired_token") {
                $error_details = "At least $($this.access_token_expires_in) seconds have passed from executing !$script:COMMAND_PREFIX-auth-start, Please run the ***$script:COMMAND_PREFIX-auth-start*** command again."
            } else {
                $error_details = $response_body
            }

            throw "Unable to get access token for your account, $error_details"
        }
        # Update object properties
        $this.access_token = $response_body.access_token
        $this.refresh_token = $response_body.refresh_token
        $this.access_token_expires_in = [int]::Parse($response_body.expires_in)
        $this.access_token_creation_time = [int][double]::Parse((Get-Date -UFormat %s))

        return $response_body

        <#
            .DESCRIPTION
            Getting access-token and refresh-token from Microsoft application based on the device-code we go from AuthorizationRequest() method.

            .EXAMPLE
            $client.AccessTokenRequest()

            .OUTPUTS
            psobject - Raw body response.

            .LINK
            https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-device-code#authenticating-the-user
        #>
    }

    [psobject]RefreshTokenRequest() {
        # Get new token using refresh token
        try {
            $params = @{
                "URI" = "https://login.microsoftonline.com/organizations/oauth2/v2.0/token"
                "Method" = "Post"
                "Headers" = (New-Object "System.Collections.Generic.Dictionary[[String],[String]]").Add("Content-Type", "application/x-www-form-urlencoded")
                "Body" = "grant_type=refresh_token&client_id=$($this.application_id)&refresh_token=$($this.refresh_token)&scope=$($this.application_scope)"
                "NoProxy" = !$this.proxy
                "SkipCertificateCheck" = $this.insecure
            }
            $response = Invoke-WebRequest @params
            $response_body = ConvertFrom-Json $response.Content
        }
        catch {
            $response_body = ConvertFrom-Json $_.ErrorDetails.Message
            $error_details = "Unable to refresh access token for your account"

            # AADSTS50173 points to password change https://login.microsoftonline.com/error?code=50173.
            # In that case, the integration context should be overwritten and the user should execute the auth process from the begining.
            if ($response_body.error_description -like "*AADSTS50173*") {
                $this.ClearContext()
                $error_details = "The account password has been changed or reset. Please run !$script:COMMAND_PREFIX-auth-start to re-authenticate"
            }
            elseif ($response_body.error -eq "invalid_grant") {
                $error_details = "Please login to grant account permissions (After 90 days grant is expired) !$script:COMMAND_PREFIX-auth-start"
            }
            throw "$error_details. Full error message: $response_body"
        }
        # Update object properties
        $this.access_token = $response_body.access_token
        $this.refresh_token = $response_body.refresh_token
        $this.access_token_expires_in = [int]::Parse($response_body.expires_in)
        $this.access_token_creation_time = [int][double]::Parse((Get-Date -UFormat %s))

        return $response_body

        <#
            .DESCRIPTION
            Getting new access-token and refresh-token from Microsoft application based on the refresh-token we got from AccessTokenRequest() method.

            .EXAMPLE
            $client.RefreshTokenRequest()

            .OUTPUTS
            PSObject - Raw body response.

            .LINK
            https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-implicit-grant-flow#refreshing-tokens
        #>
    }

    [bool]IsDeviceCodeExpired(){
        if (!$this.device_code){
            return $true
        }
        $current_time = [int][double]::Parse((Get-Date -UFormat %s)) - 30
        $valid_until = $this.device_code_creation_time + $this.access_token_expires_in

        return $current_time -gt $valid_until

        <#
            .DESCRIPTION
            Check if device-code expired with offset of 30 seconds.

            .EXAMPLE
            $client.IsDeviceCodeExpired()

            .OUTPUTS
            bool - True If device-code expired else False.

            .LINK
            https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-configurable-token-lifetimes#configurable-token-lifetime-properties-after-the-retirement
        #>
    }

    [bool]IsAccessTokenExpired(){
        if (!$this.access_token){
            return $true
        }
        $current_time = [int][double]::Parse((Get-Date -UFormat %s)) - 30
        $valid_until = $this.access_token_creation_time + $this.access_token_expires_in

        return $current_time -gt $valid_until
        <#
            .DESCRIPTION
            Check if access-token expired with offset of 30 seconds.

            .EXAMPLE
            $client.IsAccessTokenExpired()

            .OUTPUTS
            bool - True If access-token expired else False.

            .LINK
            https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-configurable-token-lifetimes#configurable-token-lifetime-properties-after-the-retirement
        #>
    }

    RefreshTokenIfExpired(){
        if ($this.access_token -and $this.IsAccessTokenExpired()) {
            $this.RefreshTokenRequest()
        }
        <#
            .DESCRIPTION
            Refresh access token if expired, with offset of 30 seconds.

            .EXAMPLE
            $client.RefreshTokenIfExpired()
        #>
    }

    ClearContext(){
        $this.access_token = $null
        $this.refresh_token = $null
        $this.access_token_expires_in = $null
        $this.access_token_creation_time = $null
        UpdateIntegrationContext $this
        <#
            .DESCRIPTION
            Clear the token fields from the integration context on password change case.

            .EXAMPLE
            $client.ClearContext()
        #>

    }

}

class ExchangeOnlineClient {
    [string]$url
    [string]$upn
    [string]$password
    [string]$bearer_token
    [psobject]$session
    [bool]$insecure
    [bool]$proxy

    [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingPlainTextForPassword', '', Scope='Function')]
    ExchangeOnlineClient([string]$url, [string]$upn, [string]$password, [string]$bearer_token, [bool]$insecure, [bool]$proxy) {
        $this.upn = $upn
        $this.password = $password
        $this.bearer_token = $bearer_token
        $this.insecure = $insecure
        $this.proxy = $proxy
        $this.url = $url
        <#
            .DESCRIPTION
            ExchangeOnlineClient connect to Exchange Online using power-shell session (OAuth2.0) and allow interact with it.

            .PARAMETER url
            Exchange online url.

            .PARAMETER upn
            User Principal Name (UPN) is the name of a system user in an email address format.

            .PARAMETER password
            Password is filled only if authentication method is basic auth.

            .PARAMETER bearer_token
            Valid bearer token value.

            .PARAMETER insecure
            Whether to trust any TLS/SSL Certificate) or not.

            .EXAMPLE proxy
            Whether to user system proxy configuration or not.

            .EXAMPLE
            $exo_client = [ExchangeOnlineClient]::new("outlook.com", "user@microsoft.com", "dfhsdkjhkjhvkdvbihsgiu")
        #>
    }

    CreateSession() {
        $this.session = CreateNewSession -url $this.url -upn $this.upn -password $this.password -bearer_token $this.bearer_token -insecure $this.insecure -proxy $this.proxy
        <#
            .DESCRIPTION
            This method is for internal use. It creates session to Exchange Online.

            .EXAMPLE
            $client.CreateSession()

            .LINK
            https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/new-pssession?view=powershell-7
            https://docs.microsoft.com/en-us/powershell/partnercenter/multi-factor-auth?view=partnercenterps-3.0#exchange-online-powershell
        #>
    }

    CloseSession() {
        if ($this.session) {
            Remove-PSSession $this.session
        }
        <#
            .DESCRIPTION
            This method is for internal use. It creates session to Exchange Online.

            .EXAMPLE
            $client.CloseSession()

            .LINK
            https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/remove-pssession?view=powershell-7
            https://docs.microsoft.com/en-us/powershell/partnercenter/multi-factor-auth?view=partnercenterps-3.0#exchange-online-powershell
        #>
    }

    [PSObject]
    GetPolicyList([string]$identity) {
        try
        {
            $cmd_params = @{ }
            if ($identity)
            {
                $cmd_params.Identity = $identity
            }
            $this.CreateSession()
            Import-PSSession -Session $this.session -CommandName Get-SafeLinksPolicy -AllowClobber

            $results = Get-SafeLinksPolicy @cmd_params
            return $results
        }
        finally {
        # Close session to remote
        $this.CloseSession()
        }

        <#
        .DESCRIPTION
        Use this cmdlet to view Safe Links policies in your cloud-based organization.
        This cmdlet is available only in the cloud-based service.

        .PARAMETER identity
        The Identity parameter specifies the Safe Links policy that you want to view.

        You can use any value that uniquely identifies the policy. For example:
        * Name
        * Distinguished name (DN)
        * GUID

        .EXAMPLE
        GetPolicyList("1254y894-feae-9yn7-a3e1-f2483a154tft")

        .OUTPUTS
        PSObject - Raw response

        .LINK
        https://docs.microsoft.com/en-us/powershell/module/exchange/get-safelinkspolicy?view=exchange-ps
        #>
    }

    [PSObject]
    CreateUpdatePolicy([string]$command_type, [hashtable]$kwargs)
    {
        try
        {
            $cmd_params = @{
                Name = $kwargs.name
            }
            if ($kwargs.admin_display_name) {
                $cmd_params.AdminDisplayName = $kwargs.admin_display_name
            }
            if ($kwargs.custom_notification_text) {
                $cmd_params.CustomNotificationText = $kwargs.custom_notification_text
            }
            if ($kwargs.deliver_message_after_scan) {
                $cmd_params.DeliverMessageAfterScan = ConvertTo-Boolean $kwargs.deliver_message_after_scan
            }
            if ($kwargs.do_not_allow_click_through) {
                $cmd_params.DoNotAllowClickThrough = ConvertTo-Boolean $kwargs.do_not_allow_click_through
            }
            if ($kwargs.do_not_rewrite_urls) {
                $cmd_params.DoNotRewriteUrls = EncloseArgWithQuotes($kwargs.do_not_rewrite_urls)
            }
            if ($kwargs.do_not_track_user_clicks) {
                $cmd_params.DoNotTrackUserClicks = ConvertTo-Boolean $kwargs.do_not_track_user_clicks
            }
            if ($kwargs.enable_for_internal_senders) {
                $cmd_params.EnableForInternalSenders = ConvertTo-Boolean $kwargs.enable_for_internal_senders
            }
            if ($kwargs.enable_organization_branding) {
                $cmd_params.EnableOrganizationBranding = ConvertTo-Boolean $kwargs.enable_organization_branding
            }
            if ($kwargs.enable_safe_links_for_teams) {
                $cmd_params.EnableSafeLinksForTeams = ConvertTo-Boolean $kwargs.enable_safe_links_for_teams
            }
            if ($kwargs.is_enabled) {
                $cmd_params.IsEnabled = ConvertTo-Boolean $kwargs.is_enabled
            }
            if ($kwargs.scan_urls) {
                $cmd_params.ScanUrls = ConvertTo-Boolean $kwargs.scan_urls
            }
            if ($kwargs.use_translated_notification_text) {
                $cmd_params.UseTranslatedNotificationText = ConvertTo-Boolean $kwargs.use_translated_notification_text
            }

            $this.CreateSession()
            Import-PSSession -Session $this.session -CommandName New-SafeLinksPolicy -AllowClobber

            if ($command_type -eq "create") {
                $results = New-SafeLinksPolicy @cmd_params
            }
            else {
                $results = Set-SafeLinksPolicy @cmd_params
            }
            return $results
        }
        finally
        {
            $this.CloseSession()
        }

        <#
        .DESCRIPTION
        Use this cmdlet to create or update Safe Links policies in your cloud-based organization.
        This cmdlet is available only in the cloud-based service.

        .EXAMPLE
        CreateUpdatePolicy("1254y894-feae-9yn7-a3e1-f2483a154tft")

        .OUTPUTS
        PSObject - Raw response

        .LINK
        https://docs.microsoft.com/en-us/powershell/module/exchange/new-safelinkspolicy?view=exchange-ps
        https://docs.microsoft.com/en-us/powershell/module/exchange/set-safelinkspolicy?view=exchange-ps
        #>
    }

    RemovePolicy([string]$identity) {
        try
        {
            $this.CreateSession()
            Import-PSSession -Session $this.session -CommandName Remove-SafeLinksPolicy -AllowClobber

            Remove-SafeLinksPolicy -Identity $identity -Confirm:$false -WarningAction:SilentlyContinue > $null
        }
        finally
        {
            $this.CloseSession()
        }


        <#
        .DESCRIPTION
        Use this cmdlet to remove Safe Links policies from your cloud-based organization.
        This cmdlet is available only in the cloud-based service.

        .PARAMETER identity
        The Identity parameter specifies the Safe Links policy that you want to remove.

        You can use any value that uniquely identifies the policy. For example:
        * Name
        * Distinguished name (DN)
        * GUID

        .EXAMPLE
        RemovePolicy("1254y894-feae-9yn7-a3e1-f2483a154tft")

        .OUTPUTS
        PSObject - Raw response

        .LINK
        https://docs.microsoft.com/en-us/powershell/module/exchange/remove-safelinkspolicy?view=exchange-ps
        #>
    }

    [PSObject]
    GetRules([string]$identity, [string]$state)
    {
        try
        {
            $cmd_params = @{ }
            if ($identity) {
                $cmd_params.Identity = $identity
            }
            if ($state) {
                $cmd_params.State = $state
            }
            $this.CreateSession()
            Import-PSSession -Session $this.session -CommandName Get-SafeLinksRule -AllowClobber

            $results = Get-SafeLinksRule @cmd_params
            return $results

        }
        finally
        {
            $this.CloseSession()
        }

        <#
        .DESCRIPTION
        Use this cmdlet to view Safe Links rules in your cloud-based organization.
        This cmdlet is available only in the cloud-based service.

        .PARAMETER identity
        The Identity parameter specifies the Safe Links rule that you want to view.

        You can use any value that uniquely identifies the policy. For example:
        * Name
        * Distinguished name (DN)
        * GUID

        .EXAMPLE
        GetRules("1254y894-feae-9yn7-a3e1-f2483a154tft")

        .OUTPUTS
         PSObject- Raw response

        .LINK
        https://docs.microsoft.com/en-us/powershell/module/exchange/get-safelinksrule?view=exchange-ps
        #>
    }

    [PSObject]
    CreateUpdateRule([string]$command_type, [hashtable]$kwargs)
    {
        try {
            $cmd_params = @{
                Name = $kwargs.name
            }

            if ($kwargs.safe_links_policy) {
                $cmd_params.SafeLinksPolicy = $kwargs.safe_links_policy
            }
            if ($kwargs.comments) {
                $cmd_params.Comments = $kwargs.comments
            }
            if ($kwargs.enabled) {
                $cmd_params.Enabled = ConvertTo-Boolean $kwargs.enabled
            }
            if ($kwargs.except_if_recipient_domain_is) {
                $cmd_params.ExceptIfRecipientDomainIs = $kwargs.except_if_recipient_domain_is
            }
            if ($kwargs.except_if_sent_to) {
                $cmd_params.ExceptIfSentTo = EncloseArgWithQuotes($kwargs.except_if_sent_to)
            }
            if ($kwargs.except_if_sent_to_member_of) {
                $cmd_params.ExceptIfSentToMemberOf = $kwargs.except_if_sent_to_member_of
            }
            if ($kwargs.priority) {
                $cmd_params.Priority = $kwargs.priority -as [Int32]
            }
            if ($kwargs.recipient_domain_is) {
                $cmd_params.RecipientDomainIs = EncloseArgWithQuotes($kwargs.recipient_domain_is)
            }
            if ($kwargs.sent_to) {
                $cmd_params.SentTo =  EncloseArgWithQuotes($kwargs.sent_to)
            }
            if ($kwargs.sent_to_member_of) {
                $cmd_params.SentToMemberOf = EncloseArgWithQuotes($kwargs.sent_to_member_of)
            }

            $this.CreateSession()

            if ($command_type -eq "create") {
                Import-PSSession -Session $this.session -CommandName New-SafeLinksRule -AllowClobber
                $results = New-SafeLinksRule @cmd_params
            }
            else {
                Import-PSSession -Session $this.session -CommandName Set-SafeLinksRule -AllowClobber
                $results = Set-SafeLinksRule @cmd_params
            }
            return $results
        }
        finally {
            $this.CloseSession()
        }

        <#
        .DESCRIPTION
        Use this cmdlet to create or update Safe Links rules in your cloud-based organization.
        This cmdlet is available only in the cloud-based service.

        .EXAMPLE
        CreateUpdatePolicy("1254y894-feae-9yn7-a3e1-f2483a154tft")

        .OUTPUTS
        PSObject - Raw response

        .LINK
        https://docs.microsoft.com/en-us/powershell/module/exchange/new-safelinksrule?view=exchange-ps
        https://docs.microsoft.com/en-us/powershell/module/exchange/set-safelinksrule?view=exchange-ps
        #>
    }

    [PSObject]
    GetDetailReport([hashtable]$kwargs)
    {
        try
        {
            $cmd_args = @{
                "StartDate" = $kwargs.start_date
                "EndDate" = $kwargs.end_date
                }
            if ($kwargs.click_id)
            {
                $cmd_args.ClickId = $kwargs.click_id
            }
            if ($kwargs.recipient_address)
            {
                $cmd_args.RecipientAddress = EncloseArgWithQuotes($kwargs.recipient_address)
            }
            if ($kwargs.domain)
            {
                $cmd_args.Domain = $kwargs.domain
            }
            if ($kwargs.app_names)
            {
                $cmd_args.AppNameList = EncloseArgWithQuotes($kwargs.app_names)
            }
            if ($kwargs.page)
            {
                $cmd_args.Page = [int]$kwargs.page
            }
            $this.CreateSession()
            Import-PSSession -Session $this.session -CommandName Get-SafeLinksDetailReport -AllowClobber

            $results = Get-SafeLinksDetailReport @cmd_args

            return $results
        }
        finally
        {
            $this.CloseSession()
        }

    }

    [PSObject]
    GetSafeLinksDetailReport(
        [hashtable]$kwargs
    ) {
        try
        {
            $cmd_params = @{
                "StartDate" = $kwargs.start_date
                "EndDate" = $kwargs.end_date
            }
            if ($kwargs.domain) {
                $cmd_params.Domain = $kwargs.domain
            }
            if ($kwargs.app_names) {
                $cmd_params.AppNameList = ArgToList($kwargs.app_names)
            }
            if ($kwargs.action) {
                $cmd_params.Action = $kwargs.action
            }
            if ($kwargs.recipient_address) {
                $cmd_params.RecipientAddress = ArgToList($kwargs.recipient_address)
            }
            if ($kwargs.page) {
                $cmd_params.Page = [int]$kwargs.page
            }
            if ($kwargs.page_size) {
                $cmd_params.PageSize = [int]$kwargs.page_size
            }

            $this.CreateSession()
            Import-PSSession -Session $this.session -CommandName Get-SafeLinksDetailReport -AllowClobber

            $results = Get-SafeLinksDetailReport @cmd_params

            return $results

        }
        finally
        {
            $this.CloseSession()
        }

        <#
        .DESCRIPTION
        Use this cmdlet to view Safe Links report in your cloud-based organization.
        This cmdlet is available only in the cloud-based service.

        .OUTPUTS
        PSObject- Raw response

        .LINK
        https://docs.microsoft.com/en-us/powershell/module/exchange/get-safelinksdetailreport?view=exchange-ps
        #>
    }
    [PSObject]
    GetSafeLinksAggregateReport(
        [hashtable]$kwargs
    ) {
        try
        {
            $cmd_params = @{
                "StartDate" = $kwargs.start_date
                "EndDate" = $kwargs.end_date
            }
            if ($kwargs.app_names) {
                $cmd_params.AppNameList = ArgToList($kwargs.app_names)
            }
            if ($kwargs.action) {
                $cmd_params.Action = $kwargs.action
            }
            if ($kwargs.summerize_by) {
                $cmd_params.SummarizeBy = $kwargs.summerize_by
            }

            $this.CreateSession()
            Import-PSSession -Session $this.session -CommandName Get-SafeLinksAggregateReport -AllowClobber

            $results = Get-SafeLinksAggregateReport @cmd_params

            return $results

        }
        finally
        {
            $this.CloseSession()
        }

        <#
        .DESCRIPTION
        Use this cmdlet to view Safe Links report in your cloud-based organization.
        This cmdlet is available only in the cloud-based service.

        .OUTPUTS
        PSObject- Raw response

        .LINK
        https://docs.microsoft.com/en-us/powershell/module/exchange/get-safelinksaggregatereport?view=exchange-ps
        #>
    }
}

function TestModuleCommand {
    [CmdletBinding()]
    Param(
        [ExchangeOnlineClient]$exo_client
    )
    try {
        $exo_client.CreateSession()
    }
    finally {
        $exo_client.CloseSession()
    }
    $raw_response = $null
    $human_readable = "ok"
    $entry_context = $null

    Write-Output $human_readable, $entry_context, $raw_response
}

function StartAuthCommand {
    [OutputType([System.Object[]])]
    [CmdletBinding()]
    Param(
        [OAuth2DeviceCodeClient]$client
    )
    $raw_response = $client.AuthorizationRequest()
    $human_readable = "## $script:INTEGRATION_NAME - Authorize instructions
1. To sign in, use a web browser to open the page [https://microsoft.com/devicelogin](https://microsoft.com/devicelogin) and enter the code **$($raw_response.user_code)** to authenticate.
2. Run the **!$script:COMMAND_PREFIX-auth-complete** command in the War Room.
3. Run the **!$script:COMMAND_PREFIX-auth-test** command in the War Room to test the completion of the authorization process and the configured parameters."
    $entry_context = @{}

    return $human_readable, $entry_context, $raw_response
}

function CompleteAuthCommand {
    [OutputType([System.Object[]])]
    [CmdletBinding()]
    Param(
        [OAuth2DeviceCodeClient]$client
    )
    # Verify that user run start before complete
    if (!$client.device_code) {
        throw "Please run **!$script:COMMAND_PREFIX-auth-start** and follow the command instructions"
    }
    $raw_response = $client.AccessTokenRequest()
    $human_readable = "Your account **successfully** authorized!"
    $entry_context = @{}

    return $human_readable, $entry_context, $raw_response
}

function TestAuthCommand ([OAuth2DeviceCodeClient]$oclient, [ExchangeOnlineClient]$exo_client) {
    [CmdletBinding()]
    $raw_response = $oclient.RefreshTokenRequest()
    $human_readable = "**Test ok!**"
    $entry_context = @{}
    try {
        $exo_client.CreateSession()
    }
    finally {
        $exo_client.CloseSession()
    }

    return $human_readable, $entry_context, $raw_response
}

function GetPolicyListCommand {
    [CmdletBinding()]
    [OutputType([System.Object[]])]
    Param (
        [Parameter(Mandatory)][ExchangeOnlineClient]$client,
        [hashtable]$kwargs
    )

    $raw_response = $client.GetPolicyList($kwargs.identity)
    if (!$raw_response){
        return "#### No policies were found.", @{}, @{}
    }

    $human_readable = TableToMarkdown $raw_response "Results of $command"
    $entry_context = @{ "$script:INTEGRATION_ENTRY_CONTEXT.Policy(obj.Guid === val.Guid)" = $raw_response }
    return $human_readable, $entry_context, $raw_response
}

function CreateUpdatePolicyCommand {
    [CmdletBinding()]
    [OutputType([System.Object[]])]
    Param (
        [Parameter(Mandatory)][ExchangeOnlineClient]$client,
        [Parameter(Mandatory)][string]$command_type,
        [hashtable]$kwargs
    )
    $raw_response = $client.CreateUpdatePolicy(
        $command_type,
        $kwargs
    )
    if (!$raw_response){
        return "#### The policy was not ${command_type}d successfully.", @{}, @{}
    }

    $human_readable = TableToMarkdown $raw_response "Results of $command"
    $entry_context = @{ "$script:INTEGRATION_ENTRY_CONTEXT.Policy(obj.Guid === val.Guid)" = $raw_response }
    return $human_readable, $entry_context, $raw_response
}

function RemovePolicyCommand {
    [CmdletBinding()]
    [OutputType([System.Object[]])]
    Param (
        [Parameter(Mandatory)][ExchangeOnlineClient]$client,
        [hashtable]$kwargs
    )
    $identity = $kwargs.identity
    $client.RemovePolicy($identity)
    $human_readable = "#### Policy with Identity: ${identity} was removed successfully."
    return $human_readable, $null, $null
}

function GetRulesCommand {
    [CmdletBinding()]
    [OutputType([System.Object[]])]
    Param (
        [Parameter(Mandatory)][ExchangeOnlineClient]$client,
        [hashtable]$kwargs
    )
    $identity = $kwargs.identity
    $raw_response = $client.GetRules($identity, $kwargs.state)

    if (!$raw_response){
        return "#### No rules were found.", @{}, @{}
    }

    $human_readable = TableToMarkdown $raw_response "Results of $command"
    $entry_context = @{ "$script:INTEGRATION_ENTRY_CONTEXT.Rule(obj.Guid === val.Guid)" = $raw_response }
    return $human_readable, $entry_context, $raw_response
}

function CreateUpdateRuleCommand {
    [CmdletBinding()]
    [OutputType([System.Object[]])]
    Param (
        [Parameter(Mandatory)][ExchangeOnlineClient]$client,
        [Parameter(Mandatory)][string]$command_type,
        [hashtable]$kwargs
    )

    $raw_response = $client.CreateUpdateRule(
        $command_type,
        $kwargs
    )
    if (!$raw_response){
        return "#### The rule was not ${command_type}d successfully.", @{}, @{}
    }

    $human_readable = TableToMarkdown $raw_response "Results of $command"
    $entry_context = @{ "$script:INTEGRATION_ENTRY_CONTEXT.Policy(obj.Guid === val.Guid)" = $raw_response }
    return $human_readable, $entry_context, $raw_response
}

function GetDetailReportCommand {
    [CmdletBinding()]
    [OutputType([System.Object[]])]
    Param (
        [Parameter(Mandatory)][ExchangeOnlineClient]$client,
        [hashtable]$kwargs
    )
    $raw_response = $client.GetDetailReport($kwargs)
    if (!$raw_response){
        return "#### No detailed information about Safe Links results found for the given criteria.", @{}, @{}
    }

    $human_readable = TableToMarkdown $raw_response "Results of $command"
    $entry_context = @{ "$script:INTEGRATION_ENTRY_CONTEXT.DetailReport(obj.Url === val.Url)" = $raw_response }
    return $human_readable, $entry_context, $raw_response
}

function GetDetailedReport {
    [CmdletBinding()]
    [OutputType([System.Object[]])]
    Param (
        [Parameter(Mandatory)][ExchangeOnlineClient]$client,
        [hashtable]$kwargs
    )

    $raw_response = $client.GetSafeLinksDetailReport($kwargs)
    if (!$raw_response){
        return "#### No records were found.", @{}, @{}
    }

    $human_readable = TableToMarkdown $raw_response "Results of $command"
    $entry_context = @{ "$script:INTEGRATION_ENTRY_CONTEXT.DetailedReport" = CreateContextForReport $raw_response }
    return $human_readable, $entry_context, $raw_response
}

function GetAggregateReport {
    [CmdletBinding()]
    [OutputType([System.Object[]])]
    Param (
        [Parameter(Mandatory)][ExchangeOnlineClient]$client,
        [hashtable]$kwargs
    )
    $raw_response = $client.GetSafeLinksAggregateReport($kwargs)
    if (!$raw_response){
        return "#### No records were found.", @{}, @{}
    }

    $human_readable = TableToMarkdown $raw_response "Results of $command"
    $entry_context = @{ "$script:INTEGRATION_ENTRY_CONTEXT.AggregateReport" =  CreateContextForReport $raw_response }
    return $human_readable, $entry_context, $raw_response
}

function TestModuleCommand($client) {
    try {
        $client.CreateSession()
        $demisto.results("ok")
    }
    finally {
        $client.CloseSession()
    }

}

function Main {
    [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingConvertToSecureStringWithPlainText', '')]
    param()

    $command = $demisto.GetCommand()
    $command_arguments = $demisto.Args()
    $integration_params = [Hashtable] $demisto.Params()
    $insecure = (ConvertTo-Boolean $integration_params.insecure)

    <#
        Proxy currently isn't supported by PWSH New-Pssession, However partly implmentation of proxy feature still function (OAuth2.0 and redirect),
        leaving this parameter for feature development if required.
    #>
    $no_proxy = $false

    $oauth2_client = [OAuth2DeviceCodeClient]::CreateClientFromIntegrationContext($insecure, $no_proxy)
    $oauth2_client.RefreshTokenIfExpired()

    $exo_client = [ExchangeOnlineClient]::new(
        $integration_params.url,
        $integration_params.credentials.identifier,
        $integration_params.credentials.password,
        $oauth2_client.access_token,
        $insecure,
        $no_proxy
        )

    try {
        # Executing command
        $Demisto.Debug("Command being called is $command")
        switch ($command) {
            "test-module" {
                ($human_readable, $entry_context, $raw_response) = TestModuleCommand $exo_client
            }
            "$script:COMMAND_PREFIX-auth-start" {
                ($human_readable, $entry_context, $raw_response) = StartAuthCommand $oauth2_client
            }
            "$script:COMMAND_PREFIX-auth-complete" {
                ($human_readable, $entry_context, $raw_response) = CompleteAuthCommand $oauth2_client
            }
            "$script:COMMAND_PREFIX-auth-test" {
                ($human_readable, $entry_context, $raw_response) = TestAuthCommand $oauth2_client $exo_client
            }
            "$script:COMMAND_PREFIX-policy-list" {
                ($human_readable, $entry_context, $raw_response) = GetPolicyListCommand -client $exo_client -kwargs $command_arguments
            }
            "$script:COMMAND_PREFIX-policy-create" {
                ($human_readable, $entry_context, $raw_response) = CreateUpdatePolicyCommand -client $exo_client "create" -kwargs $command_arguments
            }
            "$script:COMMAND_PREFIX-policy-update" {
                ($human_readable, $entry_context, $raw_response) = CreateUpdatePolicyCommand -client $exo_client "update" -kwargs $command_arguments
            }
            "$script:COMMAND_PREFIX-policy-remove" {
                ($human_readable, $entry_context, $raw_response) = RemovePolicyCommand -client $exo_client -kwargs $command_arguments
            }
            "$script:COMMAND_PREFIX-rule-list" {
                ($human_readable, $entry_context, $raw_response) = GetRulesCommand -client $exo_client -kwargs $command_arguments
            }
            "$script:COMMAND_PREFIX-rule-create" {
                ($human_readable, $entry_context, $raw_response) = CreateUpdateRuleCommand -client $exo_client -command_type "create" -kwargs $command_arguments
            }
            "$script:COMMAND_PREFIX-rule-update" {
                ($human_readable, $entry_context, $raw_response) = CreateUpdateRuleCommand -client $exo_client -command_type "update" -kwargs $command_arguments
            }
            "$script:COMMAND_PREFIX-detail-report-get" {
                ($human_readable, $entry_context, $raw_response) = GetDetailReportCommand -client $exo_client -kwargs $command_arguments
            }
            "$script:COMMAND_PREFIX-detailed-report-get" {
                ($human_readable, $entry_context, $raw_response) = GetDetailedReport -client $exo_client -kwargs $command_arguments
            }
            "$script:COMMAND_PREFIX-aggregate-report-get" {
                ($human_readable, $entry_context, $raw_response) = GetAggregateReport -client $exo_client -kwargs $command_arguments
            }
            default {
                ReturnError "Could not recognize $command"
            }
        }
        # Updating integration context if access token changed
        UpdateIntegrationContext $oauth2_client

        # Return results to Demisto Server
        ReturnOutputs $human_readable $entry_context $raw_response | Out-Null
    }
    catch {
        $Demisto.debug("Integration: $script:INTEGRATION_NAME
        Command: $command
        Arguments: $($command_arguments | ConvertTo-Json)
        Error: $($_.Exception.Message)")
        if ($command -ne "test-module") {
            ReturnError "Error:
            Integration: $script:INTEGRATION_NAME
            Command: $command
            Arguments: $($command_arguments | ConvertTo-Json)
            Error: $($_.Exception)" | Out-Null
        }
        else {
            ReturnError $_.Exception.Message
        }
    }
}

# Execute Main when not in Tests
if ($MyInvocation.ScriptName -notlike "*.tests.ps1" -AND -NOT $Test) {
    Main
}