\n",
- " Sarah David (sara.david@jingtoso.com)\n",
- " | Completed\n",
- " | Completed\n",
- " | Completed\n",
- " | Completed\n",
- " | Completed\n",
- " | Completed\n",
- " \n",
- " Bob Smith (bob@jingtoso.com)\n",
- " | Completed\n",
- " | Completed\n",
- " | Not Started\n",
- " | Not Started\n",
- " | Not Started\n",
- " | Not Started\n",
- " \n",
- " Steve Smith (steve.smith@microsoft.com)\n",
- " | Completed\n",
- " | Completed\n",
- " | Completed\n",
- " | Completed\n",
- " | Not Started\n",
- " | Not Started\n",
- " "
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- }
- ],
- "source": [
- "$htmlCodeTable = @\"\n",
- "\n",
- "\n",
- " User | \n",
- " Form Filled Out | \n",
- " HR Paperwork Completed | \n",
- " Computer Assigned | \n",
- " MFA Number Setup | \n",
- " License Assigned | \n",
- " AD Group Assignment | \n",
- "\"@\n",
- "\n",
- "function status {\n",
- " param ($status)\n",
- " if ($status -eq 'Completed') {\n",
- " return \"\"\n",
- " } else {\n",
- " return \"\"\n",
- " }\n",
- "}\n",
- "\n",
- "ForEach ($item in $Response) {\n",
- " $insertCode = \"\n",
- " $($item.'First Name') $($item.'Last Name') ($($item.'E-mail address'))\n",
- " | $(status -status $item.'Form Filled Out') $($item.'Form Filled Out')\n",
- " | $(status -status $item.'HR Paperwork') $($item.'HR Paperwork')\n",
- " | $(status -status $item.'Computer Assigned') $($item.'Computer Assigned')\n",
- " | $(status -status $item.'MFA Number Setup') $($item.'MFA Number Setup')\n",
- " | $(status -status $item.'O365 License assigned') $($item.'O365 License assigned')\n",
- " | $(status -status $item.'AD Group assignment') $($item.'AD Group assignment')\n",
- " \"\n",
- " $htmlCodeTable = $htmlCodeTable + $insertCode\n",
- "}\n",
- "\n",
- "$htmlCodeTable | Out-Display"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Filter on specific User "
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 5,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "{\n",
- " \"@odata.etag\": \"\",\n",
- " \"ItemInternalId\": \"410fcc3c-6a16-4ee5-840d-669665082cde\",\n",
- " \"First Name\": \"Bob\",\n",
- " \"Last Name\": \"Smith\",\n",
- " \"Organization\": \"IT\",\n",
- " \"Job Title\": \"Peon\",\n",
- " \"E-mail address\": \"bob@jingtoso.com\",\n",
- " \"Form Filled out\": \"Completed\",\n",
- " \"HR Paperwork\": \"Completed\",\n",
- " \"Computer assigned\": \"Not Started\",\n",
- " \"MFA Number setup\": \"Not Started\",\n",
- " \"O365 License assigned\": \"Not Started\",\n",
- " \"AD Group assignment\": \"Not Started\"\n",
- "}\n"
- ]
- }
- ],
- "source": [
- "$Response | Where-Object {$_.'First Name' -eq 'Bob'} | ConvertTo-JSON"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 6,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "\u001b[93mJSON Payload for REST Call\u001b[0m\n",
- "{\n",
- " \"E-mail address\": \"steve.smith@microsoft.com\",\n",
- " \"MFA Number Setup\": \"Completed\",\n",
- " \"Workflow\": \"update\"\n",
- "}\n"
- ]
- }
- ],
- "source": [
- "$userDetails = @{\n",
- " \"Workflow\" = \"update\"\n",
- " \"E-mail address\" = \"steve.smith@microsoft.com\"\n",
- " \"MFA Number Setup\" = \"Completed\"\n",
- "}\n",
- "$userDetails = ($userDetails | ConvertTO-JSON); \n",
- "\n",
- "$headers = @{\n",
- " 'Content-Type' = \"application/json\"\n",
- "}\n",
- "Write-Host -ForegroundColor Yellow \"JSON Payload for REST Call\"; Write-Host $userDetails"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### Query the custom Power-Automate Flow API for a list of users"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 7,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "\n",
- "@odata.etag ItemInternalId First Name Last Name Organization Job Title E-mail address Form Filled out HR Paperwork Computer assigned\n",
- "----------- -------------- ---------- --------- ------------ --------- -------------- --------------- ------------ -----------------\n",
- " 61f0a656-2648-4624-8437-834d1684ab90 Sarah David Finance Intern sara.david@jingtoso.com Completed Completed Completed\n",
- " aa26a36b-5a41-4951-b685-e585dc4d7887 Bob Smith IT Peon bob@jingtoso.com Completed Completed Not Started\n",
- " 1c18f8ad-6ec3-4582-a413-805563f08af1 Steve Smith Whatever Marketing steve.smith@microsoft.com Completed Completed Completed\n",
- "\n"
- ]
- }
- ],
- "source": [
- "$Response = (Invoke-RestMethod `\n",
- " -method POST `\n",
- " -headers $headers `\n",
- " -body $userDetails `\n",
- " -uri \"https://prod-19.westcentralus.logic.azure.com:443/workflows/10456e974ab54633992cb73b36449ad8/triggers/manual/paths/invoke?api-version=2016-06-01&sp=%2Ftriggers%2Fmanual%2Frun&sv=1.0&sig=EzbdUgRX3GoGjOLlzlmZxTmNjHmEleAuWJOlohC9ILY\").value\n",
- " \n",
- "$Response | FT"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 8,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "\n",
- "@odata.etag : \n",
- "ItemInternalId : 61f0a656-2648-4624-8437-834d1684ab90\n",
- "First Name : Sarah\n",
- "Last Name : David\n",
- "Organization : Finance\n",
- "Job Title : Intern\n",
- "E-mail address : sara.david@jingtoso.com\n",
- "Form Filled out : Completed\n",
- "HR Paperwork : Completed\n",
- "Computer assigned : Completed\n",
- "MFA Number setup : Completed\n",
- "O365 License assigned : Completed\n",
- "AD Group assignment : Completed\n",
- "\n",
- "@odata.etag : \n",
- "ItemInternalId : aa26a36b-5a41-4951-b685-e585dc4d7887\n",
- "First Name : Bob\n",
- "Last Name : Smith\n",
- "Organization : IT\n",
- "Job Title : Peon\n",
- "E-mail address : bob@jingtoso.com\n",
- "Form Filled out : Completed\n",
- "HR Paperwork : Completed\n",
- "Computer assigned : Not Started\n",
- "MFA Number setup : Not Started\n",
- "O365 License assigned : Not Started\n",
- "AD Group assignment : Not Started\n",
- "\n",
- "@odata.etag : \n",
- "ItemInternalId : 1c18f8ad-6ec3-4582-a413-805563f08af1\n",
- "First Name : Steve\n",
- "Last Name : Smith\n",
- "Organization : Whatever\n",
- "Job Title : Marketing\n",
- "E-mail address : steve.smith@microsoft.com\n",
- "Form Filled out : Completed\n",
- "HR Paperwork : Completed\n",
- "Computer assigned : Completed\n",
- "MFA Number setup : Completed\n",
- "O365 License assigned : Not Started\n",
- "AD Group assignment : Not Started\n",
- "\n",
- "\n"
- ]
- }
- ],
- "source": [
- "$Response"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": []
- }
- ],
- "metadata": {
- "kernelspec": {
- "display_name": ".NET (PowerShell)",
- "language": "PowerShell",
- "name": ".net-powershell"
- },
- "language_info": {
- "file_extension": ".ps1",
- "mimetype": "text/x-powershell",
- "name": "PowerShell",
- "pygments_lexer": "powershell",
- "version": "7.0"
- },
- "toc-autonumbering": true
- },
- "nbformat": 4,
- "nbformat_minor": 4
-}
diff --git a/Notebooks/PowerShell/Microsoft/Graph-API/Email - Email Activity Count.ipynb b/Notebooks/PowerShell/Microsoft/Graph-API/Email - Email Activity Count.ipynb
deleted file mode 100755
index 46fbe68..0000000
--- a/Notebooks/PowerShell/Microsoft/Graph-API/Email - Email Activity Count.ipynb
+++ /dev/null
@@ -1,288 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "# Email Activity (Sent/Receive) Report\n",
- "- Replace variables with your tenant information\n",
- "- Import required modules\n",
- "- (Optional) Store your credentials\n",
- "- Authenticate with Graph API\n",
- "- Query the Graph API\n",
- "- Clean up results and Output to Scatter Chart"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Set your variables here"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 16,
- "metadata": {},
- "outputs": [],
- "source": [
- "############ This is the credentials used to authenticate with the Graph API ###################\n",
- "$credentials = @{\n",
- " tenantDomain = \"domain.com\"\n",
- " tenantId = \"xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxx\" ## AAD Tenant ID\n",
- " client_id = \"ae4fa870-23af-4ae5-a6ed-xxxxx\" ## Application Client ID\n",
- " client_secret = \"x~xxxxxxx~xxxxx~xxxxxxxxx-xxx\" ## Application Client Secret\n",
- "}"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Import required modules"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 20,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "\n",
- "CommandType Name Version Source\n",
- "----------- ---- ------- ------\n",
- "Function Get-DecryptedStringUsingMasterPassword 0.0 pp-core\n",
- "Function Get-EncryptedStringUsingMasterPassword 0.0 pp-core\n",
- "Function Get-HashOfString 0.0 pp-core\n",
- "Function Get-MasterPassword 0.0 pp-core\n",
- "Function Get-StoredCredentials 0.0 pp-core\n",
- "Function Invoke-CheckCredentials 0.0 pp-core\n",
- "Function New-StoreCredentials 0.0 pp-core\n",
- "Function Get-MSGraphAuthToken 0.0 graph\n",
- "Function Invoke-GraphAuthentication 0.0 graph\n",
- "Function Invoke-MSGraphQuery 0.0 graph\n",
- "\u001b[96m\n",
- "Please enter a master password that will be used to encrypt/decrypt this credential\u001b[0m\n"
- ]
- },
- {
- "name": "stdin",
- "output_type": "stream",
- "text": [
- " ·········\n"
- ]
- },
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "\n"
- ]
- }
- ],
- "source": [
- "$modules = @('pp-core','graph') ## These are the modules to import \n",
- "$credentialPath = \"~/.credentials/graph.credential\" ## Where to store credentials\n",
- "################## Import Graph Authentication Module #############################\n",
- "ForEach ($module in $modules) {\n",
- " Import-Module \"~/Notebooks/Powershell-Playground/PowerShell/custom-modules/$module\" -Force ## import module \n",
- " Get-Command -Module \"$module\" ## list commands in this module \n",
- "}\n",
- "\n",
- "$credentials = New-StoreCredentials -credentialPath $credentialPath -credentialArray $credentials"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Authenticate with Graph API and grab access token"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 25,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "\u001b[92m\n",
- "Authentication Parameters detected\u001b[0m\n",
- "Personal Access Token (PAT) grant_type\n",
- "\n",
- "----------------------------------------------------------------------------\n",
- "Authentiating with Microsoft Graph API using a Personal Access Token (PAT)\n",
- "\u001b[37mhttps://docs.microsoft.com/en-us/azure/storage/common/storage-auth-aad-app\u001b[0m\n",
- "----------------------------------------------------------------------------\n",
- "Requesting Token at https://login.microsoftonline.com/de40cf7e-ad5f-4245-a317-14be39cbb0ef/oauth2/token\n",
- "\u001b[92m\n",
- "\n",
- "Received Token!\u001b[0m\n",
- "\u001b[92mConnected and Access Token received and will expire \u001b[0m\n"
- ]
- }
- ],
- "source": [
- "## Get a token if authenticates properly.\n",
- "$authParams = @{\n",
- " tenantId = $credentials.tenantId\n",
- " client_id = $credentials.client_id\n",
- " client_secret = $credentials.client_secret\n",
- " resource = \"https://graph.microsoft.com\" ## resource Dont change since we want to query MDATP REST API Resource\n",
- " grant_type = \"client_credentials\" ## This is using a appliation ID and secret to authenticate\n",
- "};\n",
- "\n",
- "$tokenResponse = Invoke-GraphAuthentication -authParams $authParams"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Query the Graph API"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 22,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "URI: https://graph.microsoft.com/beta/reports/getEmailActivityCounts(period='D7')?$format=application/json\n",
- "\n",
- "@odata.type reportRefreshDate send receive read reportDate reportPeriod\n",
- "----------- ----------------- ---- ------- ---- ---------- ------------\n",
- "#microsoft.graph.emailActivitySummary 2020-06-25 2 21 1 2020-06-25 7\n",
- "#microsoft.graph.emailActivitySummary 2020-06-25 4 23 2020-06-24 7\n",
- "#microsoft.graph.emailActivitySummary 2020-06-25 2 20 2020-06-23 7\n",
- "#microsoft.graph.emailActivitySummary 2020-06-25 2 49 11 2020-06-22 7\n",
- "#microsoft.graph.emailActivitySummary 2020-06-25 2 53 2020-06-21 7\n",
- "\n"
- ]
- }
- ],
- "source": [
- "## Request Parameters\n",
- "$endpoint = \"beta/reports/getEmailActivityCounts\";\n",
- "$filters = \"(period='D$($howManyDays)')?`$format=application/json\"\n",
- "$URI = \"$resource/$($endpoint)$($filters)\"; Write-Host \"URI:\",$URI ## URL of where to query in the graph API/beta/reports/getEmailActivityCounts(period='D7')?$format=text/csv\n",
- "\n",
- "$authHeader = @{ \n",
- " 'Content-Type' = 'application/json'\n",
- " Accept = 'application/json'\n",
- " Authorization = \"Bearer $($tokenResponse.access_token)\" \n",
- "};\n",
- "\n",
- "#query Graph API and insert into $graphresponse variable\n",
- "$Result = (Invoke-RestMethod -Method Get -Uri $URI -Headers $authHeader -ErrorAction Stop).value\n",
- "$Result | Select -First 5 | Format-Table"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Clean up any empty content in send and receive and generate E-mail Activity Report"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 23,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/html": [
- "\r\n",
- "\n"
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- }
- ],
- "source": [
- "ForEach ($item in $Result) {\n",
- " if ($item.send -eq $null) {\n",
- " $item.send = 0\n",
- " }\n",
- " if ($item.receive -eq $null) {\n",
- " $item.receive = 0\n",
- " }\n",
- "}\n",
- "\n",
- "$sendSeries = [Graph.Scatter]@{\n",
- " name = \"Emails Sent\"\n",
- " x = $Result.reportDate\n",
- " y = $Result.send\n",
- "}\n",
- "\n",
- "$receiveSeries = [Graph.Scatter]@{\n",
- " name = \"Emails Received\"\n",
- " x = $Result.reportDate\n",
- " y = $Result.receive\n",
- "}\n",
- "\n",
- "$chart = @($receiveSeries, $sendSeries) | New-PlotlyChart -Title \"Emails Received vs Sent\"\n",
- "Out-Display $chart"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": []
- }
- ],
- "metadata": {
- "kernelspec": {
- "display_name": ".NET (PowerShell)",
- "language": "PowerShell",
- "name": ".net-powershell"
- },
- "language_info": {
- "file_extension": ".ps1",
- "mimetype": "text/x-powershell",
- "name": "PowerShell",
- "pygments_lexer": "powershell",
- "version": "7.0"
- },
- "toc-autonumbering": true,
- "toc-showcode": false,
- "toc-showmarkdowntxt": false
- },
- "nbformat": 4,
- "nbformat_minor": 4
-}
diff --git a/Notebooks/PowerShell/Microsoft/Graph-API/Entitlement - Access Package - List.ipynb b/Notebooks/PowerShell/Microsoft/Graph-API/Entitlement - Access Package - List.ipynb
deleted file mode 100755
index 9ef570a..0000000
--- a/Notebooks/PowerShell/Microsoft/Graph-API/Entitlement - Access Package - List.ipynb
+++ /dev/null
@@ -1,363 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "# Identity - List access packages\n",
- "\n",
- "\n",
- " \n",
- " Permission type | \n",
- " Permissions (from least to most privileged) | \n",
- " \n",
- " Delegated (work or school account) | \n",
- " EntitlementManagement.Read.All, EntitlementManagement.ReadWrite.All | \n",
- " \n",
- " \n",
- " Delegated (personal Microsoft Account) | \n",
- " Not Supported | \n",
- " \n",
- " \n",
- " Application | \n",
- " Not Supported | \n",
- " "
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Set your variables here"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 16,
- "metadata": {},
- "outputs": [],
- "source": [
- "############ This is the credentials used to authenticate with the Graph API ###################\n",
- "$credentials = @{\n",
- " tenantDomain = \"domain.com\"\n",
- " tenantId = \"xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxx\" ## AAD Tenant ID\n",
- " client_id = \"ae4fa870-23af-4ae5-a6ed-xxxxx\" ## Application Client ID\n",
- " client_secret = \"x~xxxxxxx~xxxxx~xxxxxxxxx-xxx\" ## Application Client Secret\n",
- "}"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Import required modules"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 1,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/html": [
- "\r\n",
- "\r\n",
- " \r\n",
- " The below script needs to be able to find the current output cell; this is an easy method to get it.\r\n",
- " \r\n",
- " \r\n",
- " "
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- },
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "\n",
- "CommandType Name Version Source\n",
- "----------- ---- ------- ------\n",
- "Function Get-DecryptedStringUsingMasterPassword 0.0 pp-core\n",
- "Function Get-EncryptedStringUsingMasterPassword 0.0 pp-core\n",
- "Function Get-HashOfString 0.0 pp-core\n",
- "Function Get-MasterPassword 0.0 pp-core\n",
- "Function Get-StoredCredentials 0.0 pp-core\n",
- "Function Invoke-CheckCredentials 0.0 pp-core\n",
- "Function New-StoreCredentials 0.0 pp-core\n",
- "Function Get-MSGraphAuthToken 0.0 graph\n",
- "Function Invoke-GraphAuthentication 0.0 graph\n",
- "Function Invoke-MSGraphQuery 0.0 graph\n",
- "\u001b[96m\n",
- "Please enter a master password that will be used to encrypt/decrypt this credential\u001b[0m\n"
- ]
- },
- {
- "name": "stdin",
- "output_type": "stream",
- "text": [
- " ·········\n"
- ]
- },
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "\n"
- ]
- }
- ],
- "source": [
- "$modules = @('pp-core','graph') ## These are the modules to import \n",
- "$credentialPath = \"~/.credentials/graph.credential\" ## Where to store credentials\n",
- "################## Import Graph Authentication Module #############################\n",
- "ForEach ($module in $modules) {\n",
- " Import-Module \"~/Notebooks/Powershell-Playground/PowerShell/custom-modules/$module\" -Force ## import module \n",
- " Get-Command -Module \"$module\" ## list commands in this module \n",
- "}\n",
- "\n",
- "$credentials = New-StoreCredentials -credentialPath $credentialPath -credentialArray $credentials"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Authenticate with Graph API and grab access token"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 3,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "\u001b[92m\n",
- "Authentication Parameters detected\u001b[0m\n",
- "Device Code Authentication. Standby and wait for Device Code below.\n",
- "\n",
- "To sign in, use a web browser to open the page https://microsoft.com/devicelogin and enter the code FAB46JHG5 to authenticate. \n",
- "You can also goto https://aka.ms/devicelogin\n",
- "\n",
- "Double click this code and CTRL-V to copy: \u001b[96mFAB46JHG5 \u001b[0m\n",
- "\u001b[93m\n",
- "Waiting for code \u001b[0m...\u001b[92m\n",
- "\n",
- "Received Token!\u001b[0m\n",
- "\u001b[92mConnected and Access Token received and will expire 1593208700\u001b[0m\n"
- ]
- }
- ],
- "source": [
- "## Get a token if authenticates properly.\n",
- "$authParams = @{\n",
- " tenantId = $credentials.tenantId\n",
- " client_id = $credentials.client_id\n",
- " client_secret = $credentials.client_secret\n",
- " resource = \"https://graph.microsoft.com\" ## resource Dont change since we want to query MDATP REST API Resource\n",
- " grant_type = \"device_code\" ## This is using a appliation ID and secret to authenticate\n",
- "};\n",
- "\n",
- "$tokenResponse = Invoke-GraphAuthentication -authParams $authParams"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Call Graph API for list of access packages\n",
- "Calling the url ```https://graph.microsoft.com/beta/identityGovernance/entitlementManagement/accessPackages```"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 5,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "\n",
- "URI: https://graph.microsoft.com/beta/identityGovernance/entitlementManagement/accessPackages\n",
- "AUth Header: {\n",
- " \"Accept\": \"application/json\",\n",
- " \"Content-Type\": \"application/json\",\n",
- " \"Authorization\": \"Bearer eyJ0eXAiOiJKV1QiLCJub25jZSI6InNVUU9FMTdMRTk2dkg5ckRTMnYwWmdselUteGlOX0JJVVZuM1ozR1ZMbW8iLCJhbGciOiJSUzI1NiIsIng1dCI6IlNzWnNCTmhaY0YzUTlTNHRycFFCVEJ5TlJSSSIsImtpZCI6IlNzWnNCTmhaY0YzUTlTNHRycFFCVEJ5TlJSSSJ9.eyJhdWQiOiJodHRwczovL2dyYXBoLm1pY3Jvc29mdC5jb20iLCJpc3MiOiJodHRwczovL3N0cy53aW5kb3dzLm5ldC9kZTQwY2Y3ZS1hZDVmLTQyNDUtYTMxNy0xNGJlMzljYmIwZWYvIiwiaWF0IjoxNTkzMjA0ODAwLCJuYmYiOjE1OTMyMDQ4MDAsImV4cCI6MTU5MzIwODcwMCwiYWNjdCI6MCwiYWNyIjoiMSIsImFpbyI6IkFVUUF1LzhRQUFBQUpLQWZhTE1JSGlyRXJHTEs3dkVDaEVDV01qZjJCb0lVWnZBaHBJdStWeVJpem5JZVlQL1hSdDFralgyQmZzMEk1OThqR0tYUUw0N1Nqc1psYWZQZmpRPT0iLCJhbXIiOlsicHdkIiwibWZhIl0sImFwcF9kaXNwbGF5bmFtZSI6IkRlbW8tTG9hZGVyIFJlYWRPbmx5QWNjZXNzIiwiYXBwaWQiOiJhZTRmYTg3MC0yM2FmLTRhZTUtYTZlZC01YWIxODExODU4YzciLCJhcHBpZGFjciI6IjAiLCJnaXZlbl9uYW1lIjoiSmluZyIsImlwYWRkciI6IjE3My4yMjQuMTA0LjY2IiwibmFtZSI6IkppbmciLCJvaWQiOiI0Y2RiNDJmNy1hZTU3LTQzN2UtODI5NC01M2U3MDc4YTdhMmMiLCJwbGF0ZiI6IjE0IiwicHVpZCI6IjEwMDMyMDAwNjU3NjJCOUIiLCJzY3AiOiJBdWRpdExvZy5SZWFkLkFsbCBEaXJlY3RvcnkuUmVhZC5BbGwgRW50aXRsZW1lbnRNYW5hZ2VtZW50LlJlYWQuQWxsIFJlcG9ydHMuUmVhZC5BbGwgVXNlci5SZWFkIFVzZXIuUmVhZC5BbGwgVXNlci5SZWFkQmFzaWMuQWxsIiwic2lnbmluX3N0YXRlIjpbImttc2kiXSwic3ViIjoiLVVnczM1N1NOWXZYVzB2bGctVV9RU2lmTTJMZ290dTc1anF2LW9RT2pJUSIsInRlbmFudF9yZWdpb25fc2NvcGUiOiJOQSIsInRpZCI6ImRlNDBjZjdlLWFkNWYtNDI0NS1hMzE3LTE0YmUzOWNiYjBlZiIsInVuaXF1ZV9uYW1lIjoiamluZ0Bza3lzZXJ2ZXIuY2MiLCJ1cG4iOiJqaW5nQHNreXNlcnZlci5jYyIsInV0aSI6IjlKTUpkQkFldjBXa3FXV1hXdEtJQVEiLCJ2ZXIiOiIxLjAiLCJ3aWRzIjpbIjE5NGFlNGNiLWIxMjYtNDBiMi1iZDViLTYwOTFiMzgwOTc3ZCIsIjliODk1ZDkyLTJjZDMtNDRjNy05ZDAyLWE2YWMyZDVlYTVjMyIsIjYyZTkwMzk0LTY5ZjUtNDIzNy05MTkwLTAxMjE3NzE0NWUxMCIsIjE3MzE1Nzk3LTEwMmQtNDBiNC05M2UwLTQzMjA2MmNhY2ExOCIsImU4NjExYWI4LWMxODktNDZlOC05NGUxLTYwMjEzYWIxZjgxNCJdLCJ4bXNfdGNkdCI6MTU2NzUzODM0MX0.Buv4MulXLWDoqF79BZqNKbs34jeg25ieKTj158zjELQw4MlbXbbDhXGdqDcNLR4bKpSZ_HOvPN0JUdTqWtPKPG2uYa3CyLMaZnjowDuMker45mWpw1mNY0cHHb_2c4nAJTRUO0A3MBwvKVjgXO7tvbGaAw9q_DrCg7HfotfYt0nyckJe4vy4LmfQCtO-lISE88HY4ElDZQ8JbE-owagmhW-RPMEzriZG6zg2hzHXVS4gomBX2VtA6K5D0nUtGzPj5ErJIACdV2kwZG8IlC2S127hbE_Bp4EV5iSxBBg1_414wcp6M7ofY3aWwN1ML1rYpCF3XCiOCWWrLXPTFcfy8Q\"\n",
- "}\n",
- "\u001b[96m\n",
- "Here is an example of one retrieved access package\u001b[0m\n",
- "\n",
- "id : e1c1bc0a-bf98-4370-97bb-752f00bac575\n",
- "catalogId : 11bb3d92-8dac-4d66-9d7e-15c68fd9c7e7\n",
- "displayName : Demo-Loader Access Package\n",
- "description : This is to gain access to the Demo-Loader Access Package with web apps for \n",
- " Microsoft FTE to use. \n",
- "isHidden : False\n",
- "isRoleScopesVisible : False\n",
- "createdBy : jing@skyserver.cc\n",
- "createdDateTime : 6/5/2020 6:13:44 PM\n",
- "modifiedBy : jing@skyserver.cc\n",
- "modifiedDateTime : 6/5/2020 6:13:44 PM\n",
- "\n",
- "\n"
- ]
- }
- ],
- "source": [
- "## Request Parameters\n",
- "$URI = \"https://graph.microsoft.com/beta/identityGovernance/entitlementManagement/accessPackages\" ## URL of what resource to query on Graph API\n",
- "$authHeader = @{ \n",
- " 'Content-Type' = 'application/json'\n",
- " Accept = 'application/json'\n",
- " Authorization = \"Bearer $($tokenResponse.access_token)\" \n",
- "}\n",
- "\n",
- "Write-Host \"`nURI:\",$URI\n",
- "Write-Host \"AUth Header:\", ($authHeader | ConvertTo-JSON)\n",
- "\n",
- "$Result = (Invoke-RestMethod -Method Get -Uri $URI -Headers $authHeader -ErrorAction Stop)\n",
- "\n",
- "Write-Host -ForeGroundColor Cyan \"`nHere is an example of one retrieved access package\"\n",
- "$Result.value | Select-Object -First 1 | FL ## This will take the results and limit it to 1 item."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Parse Results"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 6,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "\n",
- "displayName id catalogId\n",
- "----------- -- --------- \n",
- "Demo-Loader Access Package e1c1bc0a-bf98-4370-97bb-752f00bac575 11bb3d92-8dac-4d66-9d7e-15c68fd9c7…\n",
- "Skyserver.cc 36efa2d9-939b-46c3-afcb-d13cd77323d7 9c7a2ba0-5c7f-4b7e-8f3f-e087d7ab4b…\n",
- "\n"
- ]
- }
- ],
- "source": [
- "#query Graph API and insert into $graphresponse variable\n",
- "$filterObjects = @('displayName','id','catalogId','description')\n",
- "$Result = (Invoke-RestMethod -Method Get -Uri $URI -Headers $authHeader -ErrorAction Stop)\n",
- "$Result.value | Select-Object -Property $filterObjects"
- ]
- }
- ],
- "metadata": {
- "kernelspec": {
- "display_name": ".NET (PowerShell)",
- "language": "PowerShell",
- "name": ".net-powershell"
- },
- "language_info": {
- "file_extension": ".ps1",
- "mimetype": "text/x-powershell",
- "name": "PowerShell",
- "pygments_lexer": "powershell",
- "version": "7.0"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 4
-}
diff --git a/Notebooks/PowerShell/Microsoft/Graph-API/External Repos/msgraph-security-api-solutions b/Notebooks/PowerShell/Microsoft/Graph-API/External Repos/msgraph-security-api-solutions
deleted file mode 160000
index d5883fa..0000000
--- a/Notebooks/PowerShell/Microsoft/Graph-API/External Repos/msgraph-security-api-solutions
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit d5883fa7f5578025fd58dcc8891609aafa6fbd78
diff --git a/Notebooks/PowerShell/Microsoft/Graph-API/Graph PS Module - Basics.ipynb b/Notebooks/PowerShell/Microsoft/Graph-API/Graph PS Module - Basics.ipynb
deleted file mode 100644
index 92e351c..0000000
--- a/Notebooks/PowerShell/Microsoft/Graph-API/Graph PS Module - Basics.ipynb
+++ /dev/null
@@ -1,274 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "# Rest API - Advanced Hunting Query\n",
- "\n",
- "\n",
- " \n",
- " Type | \n",
- " Title | \n",
- " Description | \n",
- " \n",
- " \n",
- " Documentation | \n",
- " Advanced Hunting API | \n",
- " This is the documentation that refers to what permissions is required and request examples you can use to query the MDATP API | \n",
- " \n",
- " "
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Pre-requisite"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "$requiredModules = ('Microsoft.graph')\n",
- "\n",
- "Install-Module $requiredModules"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "Select-MgProfile -Name \"beta\""
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": []
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "Get-MGGroup"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "Get-MGContext"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "(Get-MGContext).scopes"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": []
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Connect to the MS Graph API using device code authentication\n",
- "Connect-MGGraph -Scopes Group.Read.All -ContextScope Process -ForceRefresh"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "$scope = \"DeviceManagementManagedDevices.ReadWrite.All\"\n",
- "\n",
- "Connect-MGGraph -Scopes $scope -ContextScope Process -ForceRefresh"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "## Find Command\n",
- "Get-Command -Module Microsoft.Graph* *command*"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "Get-MgDeviceCommand"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Import required modules and credentials "
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "$requiredModules = @('Microsoft.Graph')\n",
- "\n",
- "## This will run a script to import the required modules and credentials stored in the \"credential\" file\n",
- "$scriptPath = \"~/Notebooks/PowerShell/custom-modules/import.ps1\"\n",
- ". $scriptPath # this will run the script"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Authenticate with Graph API and get access Token for MDATP Resource"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "## Get a token if authenticates properly. \n",
- "$authParams = @{\n",
- " tenantId = $credentials.tenantId\n",
- " client_id = $credentials.client_id\n",
- " client_secret = $credentials.client_secret\n",
- " resource = \"https://api.securitycenter.windows.com\" ## resource Dont change since we want to query MDATP REST API Resource\n",
- " grant_type = \"client_credentials\" ## This is using a appliation ID and secret to authenticate\n",
- "};\n",
- "\n",
- "## this will authenticate with Graph API and token will be stored in variable.\n",
- "$tokenResponse = Invoke-GraphAuthentication -authParams $authParams"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Put your Hunting Query here"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "## Enter your query here below $Query\n",
- "$body = (@{'Query' = @\"\n",
- "\n",
- "DeviceNetworkEvents \n",
- "| where InitiatingProcessFileName =~ 'powershell.exe'\n",
- "| limit 10\n",
- "\n",
- "\"@}) | ConvertTO-JSON;"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Query the MDATP API"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Query the MDATP API Grab report schema "
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "$URI = \"https://api.securitycenter.windows.com/api/advancedqueries/run\" ## This is the URL to query with the access token.\n",
- "$header = @{ ## This is the header\n",
- " 'Content-Type' = 'application/json'\n",
- " Accept = 'application/json'\n",
- " Authorization = \"Bearer $($tokenResponse.access_token)\" }\n",
- "\n",
- "$Response = (Invoke-RestMethod -Method POST -Uri $URI -Headers $header -body $body -ErrorAction Stop)\n",
- "$Response"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Parse Results"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "## Filter by these columns\n",
- "$includeColumns = @('Timestamp','DeviceName','ActionType','RemoteIP')\n",
- "\n",
- "## These are the results\n",
- "$Result.Results | Select-Object -Property $includeColumns"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": []
- }
- ],
- "metadata": {
- "kernelspec": {
- "display_name": ".NET (PowerShell)",
- "language": "PowerShell",
- "name": ".net-powershell"
- },
- "language_info": {
- "file_extension": ".ps1",
- "mimetype": "text/x-powershell",
- "name": "PowerShell",
- "pygments_lexer": "powershell",
- "version": "7.0"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 4
-}
diff --git a/Notebooks/PowerShell/Microsoft/Graph-API/modules/GraphAuthentication.psm1 b/Notebooks/PowerShell/Microsoft/Graph-API/modules/GraphAuthentication.psm1
deleted file mode 100755
index e5fe783..0000000
--- a/Notebooks/PowerShell/Microsoft/Graph-API/modules/GraphAuthentication.psm1
+++ /dev/null
@@ -1,81 +0,0 @@
-function Invoke-GraphAuthentication {
- param ( $authParams )
-
- if (!$authParams) {
- Write-Host -ForegroundColor "Yellow" "`nNo Authentication Parameters provided`n"
- break
- } else {
- Write-Host -ForegroundColor "Green" "`nAuthentication Parameters detected"
- Write-Verbose ($authParams | ConvertTo-JSON)
- }
-
- switch ($authParams.grant_type) {
-
- "client_credentials" {
- $authUri = "https://login.microsoftonline.com/$($authParams.tenant)/oauth2";
- Write-Host "Personal Access Token (PAT) grant_type"
-
- $authBody = @{
- grant_type = "client_credentials"
- client_id = $authParams.client_id
- client_secret = $authParams.client_secret
- scope = $authParams.scope
- resource = $authParams.resource
- }
-
- Write-Host "`n----------------------------------------------------------------------------"
- Write-Host "Authentiating with Microsoft Graph API using a Personal Access Token (PAT)"
- Write-Host "https://docs.microsoft.com/en-us/azure/storage/common/storage-auth-aad-app" -ForegroundColor Gray
- Write-Host "----------------------------------------------------------------------------"
-
- $authResponse = Invoke-RestMethod -Method Post -Uri "$authUri/token" -Body $authBody -ErrorAction Stop
- return $authResponse
- }
-
- "device_code" {
- $authUri = "https://login.microsoftonline.com/$($authParams.tenant)/oauth2";
- Write-Host "Device Code Workflow"
-
- $authBody = @{
- resource = $authParams.resource
- grant_type = "device_code"
- client_id = $authParams.client_id
- }
- if ($authParams.scope) { $authBody.scope = $authParams.scope}
-
- $deviceCodeResponse = Invoke-RestMethod -Method POST -Uri "$authUri/devicecode" -Body $authBody
- $authBody.code = $deviceCodeResponse.device_code
- Write-Host "`n$($deviceCodeResponse.message) "
- $code = ($deviceCodeResponse.message -split "code " | Select-Object -Last 1) -split " to authenticate."
- Write-Host "`nDouble click this code and CTRL-V to copy: " -NoNewLine; Write-Host -ForeGroundColor cyan "$($code)"
- Set-Clipboard -Value $code
-
- Write-Host ($authBody | ConvertTo-JSON)
-
- Write-Host -ForeGroundColor Yellow "`nWaiting for code"
- While (!$tokenResponse) {
- Try {
- $tokenResponse = Invoke-RestMethod -Method POST -Uri "$authUri/token" -Body $authBody -ErrorAction Ignore
- Write-Host -ForeGroundColor Green "`nReceived Token!"
- Write-Host -ForegroundColor Green "Connected and Access Token received and will expire $($tokenResponse.expires_on)"
- return $tokenResponse
- } Catch {
- }
- }
- }
-
- "refresh_token" {
- $authUrl = "https://login.windows.net/$($authParams.tenantId)/oauth2/v2.0/token"
- Write-Host "`n----------------------------------------------------------------------------"
- Write-Host "Refreshing Access Token with Microsoft Graph API using a Refresh Token"
- Write-Host "https://docs.microsoft.com/en-us/azure/storage/common/storage-auth-aad-app" -ForegroundColor Gray
- Write-Host "----------------------------------------------------------------------------"
-
- $authResponse = Invoke-RestMethod -Method Post -Uri $authUrl -Body $authBody -ErrorAction Stop
- if ($authResponse.expires_in) {
- Write-Host -foregroundColor green "`nSuccessfully refreshed token."
- return $authResponse
- }
- }
- }
-}
\ No newline at end of file
diff --git a/Notebooks/PowerShell/Microsoft/Intune/Device Mgmt - Scripts.ipynb b/Notebooks/PowerShell/Microsoft/Intune/Device Mgmt - Scripts.ipynb
deleted file mode 100644
index d674dc4..0000000
--- a/Notebooks/PowerShell/Microsoft/Intune/Device Mgmt - Scripts.ipynb
+++ /dev/null
@@ -1,323 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "# Device Managment - Scripts\n",
- "\n",
- " Author: Jing Nghik\n",
- " Last Updated 2/9/2021\n",
- "\n",
- "Purpose: Intune will provide customer the ability to run their Powershell scripts on the enrolled windows 10 Azure Active Directory joined devices. The script can be run once or periodically.\n",
- "\n",
- "## Requirements: \n",
- "\n",
- "### Scopes Required\n",
- "- DeviceManagementManagedDevices.ReadWrite.All\n",
- "\n",
- "### A client AppID/Secret or Device Code Authentication\n",
- "[Docs.Microsoft.com - List deviceManagementScripts](https://docs.microsoft.com/en-us/graph/api/intune-shared-devicemanagementscript-list?view=graph-rest-beta)\n",
- " \n",
- " Important: Microsoft Graph APIs under the /beta version are subject to change; production use is not supported.\n",
- " Note: The Microsoft Graph API for Intune requires an active Intune license for the tenant."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Set Variables and Import required modules and credentials "
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 35,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "\n",
- "CommandType Name Version Source\n",
- "----------- ---- ------- ------\n",
- "Function Get-DecryptedStringUsingMasterPassword 0.0 pp-core\n",
- "Function Get-EncodedString 0.0 pp-core\n",
- "Function Get-EncryptedStringUsingMasterPassword 0.0 pp-core\n",
- "Function Get-HashOfString 0.0 pp-core\n",
- "Function Get-MasterPassword 0.0 pp-core\n",
- "Function Get-StoredCredentials 0.0 pp-core\n",
- "Function Invoke-CheckCredentials 0.0 pp-core\n",
- "Function New-StoreCredentials 0.0 pp-core\n",
- "Function Get-MSGraphAuthToken 0.0 graph\n",
- "Function Invoke-GraphAuthentication 0.0 graph\n",
- "Function Invoke-MSGraphQuery 0.0 graph\n",
- "\n"
- ]
- }
- ],
- "source": [
- "## Change these if required\n",
- "$resource = \"https://graph.microsoft.com\" ## resource Dont change since we want to query MDATP REST API Resource\n",
- "$grant_type = \"client_credentials\" ## This is using a device_code flow (supports: client_credentials, device_code)\n",
- "$apiVersion = \"beta\" ## Identify the version of the API ( api or beta )\n",
- "\n",
- "## Dont really need to change these unless necessary\n",
- "$VerbosePreference = \"ignore\" ## Set to 'continue to get verbose output'\n",
- "## This will run a script to import the required modules and credentials stored in the \"credential\" file\n",
- "$scriptPath = \"~/Notebooks/PowerShell/custom-modules/import.ps1\"; . $scriptPath # this will run the script"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Authenticate with Graph API and get access Token for MDATP Resource"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 36,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "\u001b[92m\n",
- "Authentication Parameters detected\u001b[0m\n",
- "Personal Access Token (PAT) grant_type\n",
- "\n",
- "----------------------------------------------------------------------------\n",
- "Authentiating with Microsoft Graph API using a Personal Access Token (PAT)\n",
- "\u001b[37mhttps://docs.microsoft.com/en-us/azure/storage/common/storage-auth-aad-app\u001b[0m\n",
- "----------------------------------------------------------------------------\n",
- "Requesting Token at https://login.microsoftonline.com/e4194ef7-b5d7-4db1-b7e9-a73af406f276/oauth2/token\n",
- "\u001b[92m\n",
- "\n",
- "Received Token!\u001b[0m\n",
- "\u001b[93mConnected and Access Token received and will expire 1612936082\u001b[0m\n",
- "\n",
- "Name Value\n",
- "---- -----\n",
- "Accept application/json\n",
- "Content-Type application/json\n",
- "Authorization Bearer eyJ0eXAiOiJKV1QiLCJub25jZSI6ImZtM2JNTWFLUVdocTZWdGZtSnpJWjRIYnNDNFZhRXpmOUdqNTJaVWI1djQiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImtp…\n",
- "\n"
- ]
- }
- ],
- "source": [
- "## Get a token if authenticates properly. \n",
- "\n",
- "$authParams = @{\n",
- " tenantId = $credentials.tenantId\n",
- " client_id = $credentials.client_id\n",
- " client_secret = $credentials.client_secret\n",
- " resource = $resource ## resource Dont change since we want to query MDATP REST API Resource\n",
- " grant_type = $grant_type ## This is using a device_code flow (supports: client_credentials, device_code)\n",
- " #scope = \"https://api.securitycenter.microsoft.com/Machine.ReadWrite.All\" ## set the scope\n",
- "};\n",
- "\n",
- "## this will authenticate with Graph API and token will be stored in variable.\n",
- "$token = (Invoke-GraphAuthentication -authParams $authParams)\n",
- "\n",
- "## This is the authentication header for REST API Call\n",
- "if ($token.access_token -ne $null) {\n",
- " $authHeader = @{ \n",
- " 'Content-Type' = 'application/json'\n",
- " Accept = 'application/json'\n",
- " Authorization = \"Bearer $($token.access_token)\" \n",
- " }\n",
- "}; $authHeader"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Get list of available scripts"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 37,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "https://graph.microsoft.com/beta/deviceManagement/deviceManagementScripts\n",
- "\n",
- "id displayName description fileName\n",
- "-- ----------- ----------- --------\n",
- "4838170d-a36e-47c0-aa4c-6ae9aa971d90 test script2 This is a test script. test2.ps1\n",
- "5456b4d2-cce1-4c4e-93c4-b4078423b620 test script This is a test script. test.ps1\n",
- "b34e96e5-9580-4228-8319-6636ecc4b3ec test script2 This is a test script. test2.ps1\n",
- "\n"
- ]
- }
- ],
- "source": [
- "## Set the path you want to query\n",
- "$endpoint = \"deviceManagement/deviceManagementScripts\"\n",
- "$method = \"GET\"\n",
- "\n",
- "## The following commands will query the graph API and output the first 5 machines in table format\n",
- "$uri = \"$($resource)/$apiVersion/$endpoint\"; $uri\n",
- "$Response = (Invoke-RestMethod -Method $method -Uri $uri -Headers $authHeader -body $body -ErrorAction Stop)\n",
- "\n",
- "## Filter columns \n",
- "$filter = @('id','displayName','description','fileName')\n",
- "$Response.value | Select-Object $filter | FT"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Create a sample script"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 30,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "\u001b[93mEncoded String: CiMjIFRoaXMgaXMgYSB0ZXN0IHNjcmlwdAplY2hvICd0ZXN0JyA+IGM6XHRlc3QudHh0Cg==\u001b[0m\n"
- ]
- }
- ],
- "source": [
- "$script = @\"\n",
- "\n",
- "## This is a test script\n",
- "echo 'test' > c:\\test.txt\n",
- "\n",
- "\"@\n",
- "\n",
- "$encodedString = Get-encodedString $script"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Create a test powershell script"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 31,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "https://graph.microsoft.com/beta/deviceManagement/deviceManagementScripts\n",
- "\n",
- "@odata.context : https://graph.microsoft.com/beta/$metadata#deviceManagement/deviceManagementScripts/$entity\n",
- "enforceSignatureCheck : True\n",
- "runAs32Bit : True\n",
- "id : b34e96e5-9580-4228-8319-6636ecc4b3ec\n",
- "displayName : test script2\n",
- "description : This is a test script.\n",
- "scriptContent : CiMjIFRoaXMgaXMgYSB0ZXN0IHNjcmlwdAplY2hvICd0ZXN0JyA+IGM6XHRlc3QudHh0Cg==\n",
- "createdDateTime : 2/10/2021 3:57:39 AM\n",
- "lastModifiedDateTime : 2/10/2021 3:57:39 AM\n",
- "runAsAccount : user\n",
- "fileName : test2.ps1\n",
- "roleScopeTagIds : {0}\n",
- "\n",
- "\n"
- ]
- }
- ],
- "source": [
- "## Set the path you want to query\n",
- "$endpoint = \"deviceManagement/deviceManagementScripts\"\n",
- "$method = \"POST\"\n",
- "\n",
- "$body = @\"\n",
- "{\n",
- " \"@odata.type\": \"#microsoft.graph.deviceManagementScript\",\n",
- " \"displayName\": \"test script2\",\n",
- " \"description\": \"This is a test script.\",\n",
- " \"scriptContent\": \"$encodedString\",\n",
- " \"runAsAccount\": \"user\",\n",
- " \"enforceSignatureCheck\": true,\n",
- " \"fileName\": \"test2.ps1\",\n",
- " \"runAs32Bit\": true\n",
- "}\n",
- "\"@\n",
- "\n",
- "## The following commands will query the graph API and output the first 5 machines in table format\n",
- "$uri = \"$($resource)/beta/$endpoint\"; $uri\n",
- "$Response = (Invoke-RestMethod -Method $method -Uri $uri -Headers $authHeader -body $body -ErrorAction Stop)\n",
- "$Response\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Assign script to a group of devices\n",
- "- https://docs.microsoft.com/en-us/graph/api/intune-shared-devicemanagementscript-assign?view=graph-rest-beta"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "## Set the path you want to query\n",
- "$endpoint = \"deviceManagement/deviceManagementScripts\"\n",
- "$method = \"POST\"\n",
- "\n",
- "$body = @\"\n",
- "{\n",
- " \"@odata.type\": \"#microsoft.graph.deviceManagementScript\",\n",
- " \"displayName\": \"test script2\",\n",
- " \"description\": \"This is a test script.\",\n",
- " \"scriptContent\": \"$encodedString\",\n",
- " \"runAsAccount\": \"user\",\n",
- " \"enforceSignatureCheck\": true,\n",
- " \"fileName\": \"test2.ps1\",\n",
- " \"runAs32Bit\": true\n",
- "}\n",
- "\"@\n",
- "\n",
- "## The following commands will query the graph API and output the first 5 machines in table format\n",
- "$uri = \"$($resource)/beta/$endpoint\"; $uri\n",
- "$Response = (Invoke-RestMethod -Method $method -Uri $uri -Headers $authHeader -body $body -ErrorAction Stop)\n",
- "$Response"
- ]
- }
- ],
- "metadata": {
- "kernelspec": {
- "display_name": ".NET (PowerShell)",
- "language": "PowerShell",
- "name": ".net-powershell"
- },
- "language_info": {
- "file_extension": ".ps1",
- "mimetype": "text/x-powershell",
- "name": "PowerShell",
- "pygments_lexer": "powershell",
- "version": "7.0"
- },
- "toc-autonumbering": true,
- "toc-showmarkdowntxt": true
- },
- "nbformat": 4,
- "nbformat_minor": 4
-}
diff --git a/Notebooks/PowerShell/Microsoft/Intune/External Repos/msgraph-intune-samples b/Notebooks/PowerShell/Microsoft/Intune/External Repos/msgraph-intune-samples
deleted file mode 160000
index ddc6aef..0000000
--- a/Notebooks/PowerShell/Microsoft/Intune/External Repos/msgraph-intune-samples
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit ddc6aeff48e046d564675573fd6f8e3a12e0d0b4
diff --git a/Notebooks/PowerShell/Microsoft/Power-BI/Embedded PowerBI.ipynb b/Notebooks/PowerShell/Microsoft/Power-BI/Embedded PowerBI.ipynb
deleted file mode 100755
index f8c4d5f..0000000
--- a/Notebooks/PowerShell/Microsoft/Power-BI/Embedded PowerBI.ipynb
+++ /dev/null
@@ -1,60 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "code",
- "execution_count": 3,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/html": [
- ""
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- }
- ],
- "source": [
- "#!html\n",
- "\n",
- ""
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": []
- }
- ],
- "metadata": {
- "kernelspec": {
- "display_name": ".NET (PowerShell)",
- "language": "PowerShell",
- "name": ".net-powershell"
- },
- "language_info": {
- "file_extension": ".ps1",
- "mimetype": "text/x-powershell",
- "name": "PowerShell",
- "pygments_lexer": "powershell",
- "version": "7.0"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 4
-}
diff --git a/Notebooks/PowerShell/Microsoft/Security/Azure Sentinel/AzSentinel Module - Add Rule.ipynb b/Notebooks/PowerShell/Microsoft/Security/Azure Sentinel/AzSentinel Module - Add Rule.ipynb
deleted file mode 100755
index ba8412e..0000000
--- a/Notebooks/PowerShell/Microsoft/Security/Azure Sentinel/AzSentinel Module - Add Rule.ipynb
+++ /dev/null
@@ -1,258 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "# AzSentinel Module"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Documentation\n",
- "### Wortell\n",
- "- [Blog] - [Azure Sentinel: automating your Use Cases with PowerShell and the #AzSentinel module](https://medium.com/wortell/azure-sentinel-automating-your-use-cases-with-powershell-and-the-azsentinel-module-380606e601f5)\n",
- "- Wortell - [Azure Sentinel 'AZSentinel' Module Github](https://github.com/wortell/AZSentinel) - Wortell created an AZSentinel Module to easily work with Azure Sentinel\n",
- "- Wortell - [Sample KQL Sigma Rules](https://github.com/wortell/KQL) - Library of already converted Sigma Rules that are ready to add to AZSentinel"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Import the Module from PSGallery"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 2,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "\n",
- "Get-AzSentinelAlertRule Get-AzSentinelAlertRuleAction\n",
- "Get-AzSentinelHuntingRule Get-AzSentinelIncident\n",
- "Import-AzSentinelAlertRule Import-AzSentinelHuntingRule\n",
- "New-AzSentinelAlertRule New-AzSentinelAlertRuleAction\n",
- "New-AzSentinelHuntingRule Remove-AzSentinelAlertRule\n",
- "Remove-AzSentinelAlertRuleAction Remove-AzSentinelHuntingRule\n",
- "Set-AzSentinel Update-AzSentinelIncident\n",
- "\n"
- ]
- }
- ],
- "source": [
- "Install-Module AzSentinel\n",
- "Import-Module AzSentinel"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 4,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "\n",
- "Get-AzSentinelAlertRule Get-AzSentinelAlertRuleAction\n",
- "Get-AzSentinelHuntingRule Get-AzSentinelIncident\n",
- "Import-AzSentinelAlertRule Import-AzSentinelHuntingRule\n",
- "New-AzSentinelAlertRule New-AzSentinelAlertRuleAction\n",
- "New-AzSentinelHuntingRule Remove-AzSentinelAlertRule\n",
- "Remove-AzSentinelAlertRuleAction Remove-AzSentinelHuntingRule\n",
- "Set-AzSentinel Update-AzSentinelIncident\n",
- "\n"
- ]
- }
- ],
- "source": [
- "Get-Command -Module AzSentinel | FW"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Add a new Azure Sentinel Rule\n",
- "Use the following template to create your rule\n",
- "\n",
- "``` powershell\n",
- "{\n",
- " \"analytics\": [\n",
- " {\n",
- " \"displayName\": \"string\",\n",
- " \"description\": \"string\",\n",
- " \"severity\": \"High\",\n",
- " \"enabled\": true,\n",
- " \"query\": \"SecurityEvent | where EventID == \\\"4688\\\" | where CommandLine contains \\\"-noni -ep bypass $\\\"\",\n",
- " \"queryFrequency\": \"5H\",\n",
- " \"queryPeriod\": \"5H\",\n",
- " \"triggerOperator\": \"GreaterThan\",\n",
- " \"triggerThreshold\": 5,\n",
- " \"suppressionDuration\": \"6H\",\n",
- " \"suppressionEnabled\": false,\n",
- " \"tactics\": [\n",
- " \"Persistence\",\n",
- " \"LateralMovement\",\n",
- " \"Collection\"\n",
- " ],\n",
- " \"playbookName\": \"string\"\n",
- " }\n",
- " ]\n",
- "}\n",
- "```"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Add your new JSON Rule to Azure Sentinel\n",
- "\n",
- "'''\n",
- " $displayName = \"string\"\n",
- " $description = \"string\"\n",
- " $severity = \"High\"\n",
- " $enabled = $true\n",
- " $queryFrequency = \"5H\"\n",
- " $queryPeriod = \"5H\"\n",
- " $triggerOperator = \"GreaterThan\"\n",
- " $triggerThreshold = 5\n",
- " $suppressionDuration = \"6H\"\n",
- " $suppressionEnabled = $false\n",
- " $tactics = @('Persistence','LateralMovement','Collection')\n",
- " $playbookName = \"string\"\n",
- "'''"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 30,
- "metadata": {},
- "outputs": [],
- "source": [
- "$displayName = \"string\"\n",
- "$description = \"string\"\n",
- "$severity = \"High\"\n",
- "$enabled = $true\n",
- "$queryFrequency = \"5H\"\n",
- "$queryPeriod = \"5H\"\n",
- "$triggerOperator = \"GreaterThan\"\n",
- "$triggerThreshold = 5\n",
- "$suppressionDuration = \"6H\"\n",
- "$suppressionEnabled = $false\n",
- "$tactics = @('Persistence','LateralMovement','Collection')\n",
- "$playbookName = \"string\""
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 5,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "\u001b[93mHunting Query\n",
- "\u001b[0m\n",
- "SecurityEvent \n",
- "| where EventID == '4688'\n",
- "| where CommandLine contains \"-noni -ep bypass $\"\n",
- "\u001b[93m\n",
- "JSON Body\n",
- "\u001b[0m\n",
- "{\n",
- " \"analytics\": {\n",
- " \"description\": \"string\",\n",
- " \"suppressionEnabled\": false,\n",
- " \"query\": \"SecurityEvent \\n| where EventID == '4688'\\n| where CommandLine contains \\\"-noni -ep bypass $\\\"\",\n",
- " \"playbookName\": \"string\",\n",
- " \"triggerThreshold\": 5,\n",
- " \"severity\": \"High\",\n",
- " \"enabled\": true,\n",
- " \"queryPeriod\": \"5H\",\n",
- " \"tactics\": [\n",
- " \"Persistence\",\n",
- " \"LateralMovement\",\n",
- " \"Collection\"\n",
- " ],\n",
- " \"queryFrequency\": \"5H\",\n",
- " \"triggerOperator\": \"GreaterThan\",\n",
- " \"displayName\": \"string\",\n",
- " \"suppressionDuration\": \"6H\"\n",
- " }\n",
- "}\n"
- ]
- }
- ],
- "source": [
- "$query = @\"\n",
- "SecurityEvent \n",
- "| where EventID == '4688'\n",
- "| where CommandLine contains \"-noni -ep bypass $\"\n",
- "\"@\n",
- "\n",
- "Write-Host -Foreground yellow \"Hunting Query`n\"\n",
- "$query\n",
- "\n",
- "Write-Host -Foreground Yellow \"`nJSON Body`n\"\n",
- "$newRule = @{\n",
- " analytics = (\n",
- " @{\n",
- " displayName = \"string\"\n",
- " description = \"string\"\n",
- " severity = \"High\"\n",
- " enabled = $true\n",
- " query = $query\n",
- " queryFrequency = \"5H\"\n",
- " queryPeriod = \"5H\"\n",
- " triggerOperator = \"GreaterThan\"\n",
- " triggerThreshold = 5\n",
- " suppressionDuration = \"6H\"\n",
- " suppressionEnabled = $false\n",
- " tactics = @(\n",
- " \"Persistence\",\n",
- " \"LateralMovement\",\n",
- " \"Collection\"\n",
- " )\n",
- " playbookName = \"string\"\n",
- " }\n",
- " )\n",
- "}\n",
- "\n",
- "$newRule | ConvertTo-JSON"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": []
- }
- ],
- "metadata": {
- "kernelspec": {
- "display_name": ".NET (PowerShell)",
- "language": "PowerShell",
- "name": ".net-powershell"
- },
- "language_info": {
- "file_extension": ".ps1",
- "mimetype": "text/x-powershell",
- "name": "PowerShell",
- "pygments_lexer": "powershell",
- "version": "7.0"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 4
-}
diff --git a/Notebooks/PowerShell/Microsoft/Security/Azure Sentinel/External Repos/Azure-Sentinel-Repo b/Notebooks/PowerShell/Microsoft/Security/Azure Sentinel/External Repos/Azure-Sentinel-Repo
deleted file mode 160000
index 6a3126b..0000000
--- a/Notebooks/PowerShell/Microsoft/Security/Azure Sentinel/External Repos/Azure-Sentinel-Repo
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit 6a3126b42d6c2e18e4c08c5dfae9e68eb51ef070
diff --git a/Notebooks/PowerShell/Microsoft/Security/Azure Sentinel/Query Sentinel via Rest API.ipynb b/Notebooks/PowerShell/Microsoft/Security/Azure Sentinel/Query Sentinel via Rest API.ipynb
deleted file mode 100755
index 42b5b3c..0000000
--- a/Notebooks/PowerShell/Microsoft/Security/Azure Sentinel/Query Sentinel via Rest API.ipynb
+++ /dev/null
@@ -1,315 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "# Querying Azure Sentinel via REST API using a Personal Access Token (PAT)\n",
- "\n",
- "\n",
- " \n",
- " Type | \n",
- " Title | \n",
- " Description | \n",
- " \n",
- " \n",
- " Documentation | \n",
- " Extending Azure Sentinel: APIs, Integration and management automation | \n",
- " Its highly recommended to follow this guide to get familiar with navigating and using Jupyter Notebooks. | \n",
- " \n",
- " \n",
- " Tech Community | \n",
- " Access Azure Sentinel Log Analytics via API (Part 1) | \n",
- " @rinure wrote a good article explaining how to query the API. Use this as a reference to understand how to query the Azure Sentinel API. | \n",
- " \n",
- " "
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Set your variables here"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 9,
- "metadata": {},
- "outputs": [],
- "source": [
- "############ This is the credentials used to authenticate with the Graph API ###################\n",
- "#$credentials = @{\n",
- "# tenantDomain = \"domain.com\"\n",
- "# tenantId = \"xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxx\" ## AAD Tenant ID\n",
- "# client_id = \"ae4fa870-23af-4ae5-a6ed-xxxxx\" ## Application Client ID\n",
- "# client_secret = \"x~xxxxxxx~xxxxx~xxxxxxxxx-xxx\" ## Application Client Secret\n",
- "#}\n",
- "\n",
- "$sentinelWorkspaceId = \"a8960181-0bde-4955-9f94-2c12a36cc900\""
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Import required modules"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 2,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "\n",
- "CommandType Name Version Source\n",
- "----------- ---- ------- ------\n",
- "Function Get-DecryptedStringUsingMasterPassword 0.0 pp-core\n",
- "Function Get-EncryptedStringUsingMasterPassword 0.0 pp-core\n",
- "Function Get-HashOfString 0.0 pp-core\n",
- "Function Get-MasterPassword 0.0 pp-core\n",
- "Function Get-StoredCredentials 0.0 pp-core\n",
- "Function Invoke-CheckCredentials 0.0 pp-core\n",
- "Function New-StoreCredentials 0.0 pp-core\n",
- "Function Get-MSGraphAuthToken 0.0 graph\n",
- "Function Invoke-GraphAuthentication 0.0 graph\n",
- "Function Invoke-MSGraphQuery 0.0 graph\n",
- "\u001b[96m\n",
- "Please enter a master password that will be used to encrypt/decrypt this credential\u001b[0m\n"
- ]
- },
- {
- "name": "stdin",
- "output_type": "stream",
- "text": [
- " ·········\n"
- ]
- },
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "\n"
- ]
- }
- ],
- "source": [
- "$modules = @('pp-core','graph') ## These are the modules to import \n",
- "$credentialPath = \"~/.credentials/graph.credential\" ## Where to store credentials\n",
- "################## Import Graph Authentication Module #############################\n",
- "ForEach ($module in $modules) {\n",
- " Import-Module \"~/Notebooks/Powershell-Playground/PowerShell/custom-modules/$module\" -Force ## import module \n",
- " Get-Command -Module \"$module\" ## list commands in this module \n",
- "}\n",
- "\n",
- "$credentials = New-StoreCredentials -credentialPath $credentialPath -credentialArray $credentials"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 4,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "\u001b[92m\n",
- "Authentication Parameters detected\u001b[0m\n",
- "Personal Access Token (PAT) grant_type\n",
- "\n",
- "----------------------------------------------------------------------------\n",
- "Authentiating with Microsoft Graph API using a Personal Access Token (PAT)\n",
- "\u001b[37mhttps://docs.microsoft.com/en-us/azure/storage/common/storage-auth-aad-app\u001b[0m\n",
- "----------------------------------------------------------------------------\n",
- "Requesting Token at https://login.microsoftonline.com/de40cf7e-ad5f-4245-a317-14be39cbb0ef/oauth2/token\n",
- "\u001b[92m\n",
- "\n",
- "Received Token!\u001b[0m\n",
- "\u001b[92mConnected and Access Token received and will expire \u001b[0m\n"
- ]
- }
- ],
- "source": [
- "## Get a token if authenticates properly.\n",
- "$authParams = @{\n",
- " tenantId = $credentials.tenantId\n",
- " client_id = $credentials.client_id\n",
- " client_secret = $credentials.client_secret\n",
- " resource = \"https://api.loganalytics.io\" ## resource Dont change since we want to query MDATP REST API Resource\n",
- " grant_type = \"client_credentials\" ## This is using a appliation ID and secret to authenticate\n",
- "}\n",
- "\n",
- "$tokenResponse = Invoke-GraphAuthentication -authParams $authParams"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Put your Azure Sentinel Hunting Query here"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 6,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "\u001b[93m\n",
- "Query\u001b[0m\n",
- "\n",
- "SecurityAlert\n",
- "\n",
- "\u001b[93mJSON\u001b[0m\n",
- "{\n",
- " \"query\": \"\\nSecurityAlert\\n\",\n",
- " \"timespan\": \"\"\n",
- "}\n"
- ]
- }
- ],
- "source": [
- "## Enter your query here\n",
- "$query = @\"\n",
- "\n",
- "SecurityAlert\n",
- "\n",
- "\"@\n",
- "\n",
- "$timeSpan = \"\" ## You can leave blank or specify a date. But something HAS to be there. \n",
- " \n",
- "## This is the query converted to JSON format\n",
- "$body = (@{\n",
- " query = $Query\n",
- " timespan = $timeSpan \n",
- "} | ConvertTO-JSON)\n",
- "Write-Host -ForeGround Yellow \"`nQuery\"; $Query\n",
- "Write-Host -ForeGround Yellow \"JSON\"; $body"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Query Graph API and insert into $graphresponse variable"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 12,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "a8960181-0bde-4955-9f94-2c12a36cc900\n",
- "\n",
- "Wednesday, June 10, 2020 7:43:02 PM\n",
- "DLP - Sharepoint - Financial sensitive file(s) shared externally\n",
- "DLP - Sharepoint - Financial sensitive file(s) shared externally\n",
- "High\n",
- "File policy 'DLP - Sharepoint - Financial sensitive file(s) shared externally' was matched by 'Credit_Card_Form_SP_20200610-T0239.docx'\n",
- "MCAS\n",
- "Microsoft\n",
- "B782FAF8-F546-37A1-979B-340DE4AFF1C2\n",
- "56fb8160-5d9c-c29b-be35-be169678b9bf\n",
- "\n",
- "\n",
- "MCAS_ALERT_CABINET_EVENT_MATCH_FILE\n",
- "Unknown\n",
- "\n",
- "False\n",
- "Wednesday, June 10, 2020 7:42:56 PM\n",
- "Wednesday, June 10, 2020 7:42:56 PM\n",
- "Wednesday, June 10, 2020 7:43:02 PM\n",
- "\n",
- "{\n",
- " \"Cloud Applications\": \"Microsoft SharePoint Online\"\n",
- "}\n",
- "[\n",
- " {\n",
- " \"$id\": \"3\",\n",
- " \"AppId\": 20892,\n",
- " \"Name\": \"Microsoft SharePoint Online\",\n",
- " \"InstanceName\": \"Microsoft SharePoint Online\",\n",
- " \"Type\": \"cloud-application\"\n",
- " },\n",
- " {\n",
- " \"$id\": \"4\",\n",
- " \"Name\": \"bob\",\n",
- " \"UPNSuffix\": \"jingtoso.com\",\n",
- " \"AadUserId\": \"6836ed6d-2a15-4889-ad24-fbda46b5ffda\",\n",
- " \"Type\": \"account\"\n",
- " }\n",
- "]\n",
- "Detection\n",
- "\n",
- "\n",
- "[\n",
- " {\n",
- " \"Href\": \"https://skyserver.portal.cloudappsecurity.com/#/policy/?id=eq(5e2781b30d60ec20fe2951a2,)\",\n",
- " \"Category\": null,\n",
- " \"Label\": \"Cloud App Security policy ID\",\n",
- " \"Type\": \"webLink\"\n",
- " },\n",
- " {\n",
- " \"Href\": \"https://skyserver.portal.cloudappsecurity.com/#/alerts/5ee137c036159cde5db29d6b\",\n",
- " \"Category\": null,\n",
- " \"Label\": \"Cloud App Security alert ID\",\n",
- " \"Type\": \"webLink\"\n",
- " }\n",
- "]\n",
- "Microsoft Cloud App Security\n",
- "\n",
- "\n",
- "SecurityAlert\n",
- "\n"
- ]
- }
- ],
- "source": [
- "$URI = \"https://api.loganalytics.io/v1/workspaces/$sentinelWorkspaceId/query\"\n",
- "$header = @{ \n",
- " 'Content-Type' = 'application/json'\n",
- " Accept = 'application/json'\n",
- " Authorization = \"Bearer $($tokenResponse.access_token)\" \n",
- "}\n",
- "\n",
- "$Result = (Invoke-RestMethod -Method POST -Uri $URI -Headers $header -body $body -ErrorAction Stop)\n",
- "$Result.tables.rows | Select -First 1"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": []
- }
- ],
- "metadata": {
- "kernelspec": {
- "display_name": ".NET (PowerShell)",
- "language": "PowerShell",
- "name": ".net-powershell"
- },
- "language_info": {
- "file_extension": ".ps1",
- "mimetype": "text/x-powershell",
- "name": "PowerShell",
- "pygments_lexer": "powershell",
- "version": "7.0"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 4
-}
diff --git a/Notebooks/PowerShell/Microsoft/Security/Azure Sentinel/README.md b/Notebooks/PowerShell/Microsoft/Security/Azure Sentinel/README.md
deleted file mode 100755
index 2ce36a5..0000000
--- a/Notebooks/PowerShell/Microsoft/Security/Azure Sentinel/README.md
+++ /dev/null
@@ -1,14 +0,0 @@
-# Azure Sentinel
-
-- Both Query Sentinel notebooks were tested and looks to work now. Working on AzSentinel Module
-
-## Helpful Links
-
-### Tech Community
-- [Azure Sentinel Tech Community](https://techcommunity.microsoft.com/t5/azure-sentinel/bg-p/AzureSentinelBlog)
-- Access Azure Sentinel Log Analytics via API (Part 1)
-- Extending Azure Sentinel: APIs, Integration and management automation
-- [Ingest Sample CEF data into Azure Sentinel - @Alp Babayigit](https://techcommunity.microsoft.com/t5/azure-sentinel/ingest-sample-cef-data-into-azure-sentinel/ba-p/1064158)
-
-### Github Repositories
-- [@BlueTeamLabs - Sentinel Attaack Repo](https://github.com/BlueTeamLabs/sentinel-attack)
diff --git a/Notebooks/PowerShell/Microsoft/Security/Defender/External Repos/Defender-Hunting-Queries b/Notebooks/PowerShell/Microsoft/Security/Defender/External Repos/Defender-Hunting-Queries
deleted file mode 160000
index dfffcd4..0000000
--- a/Notebooks/PowerShell/Microsoft/Security/Defender/External Repos/Defender-Hunting-Queries
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit dfffcd47afdf71d327a36ab3f87eda33d9da323c
diff --git a/Notebooks/PowerShell/Microsoft/Security/MCAS/MCAS Module - Get Activity.ipynb b/Notebooks/PowerShell/Microsoft/Security/MCAS/MCAS Module - Get Activity.ipynb
deleted file mode 100755
index 3b06e56..0000000
--- a/Notebooks/PowerShell/Microsoft/Security/MCAS/MCAS Module - Get Activity.ipynb
+++ /dev/null
@@ -1,155 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "# MCAS PS Module - Import Module and Authenticate"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Import [Unofficial] MCAS Powershell module from Github Repository\n",
- "[MCAS Powershell Module [Unofficial] - Github Repo](https://github.com/microsoft/MCAS)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "$host.UI.RawUI.BufferSize = [System.Management.Automation.Host.Size]::new(200, 50) ## Corrects the output\n",
- "Install-Module MCAS\n",
- "#Import-Module MCAS \n",
- "\n",
- "# Grabbing commands available\n",
- "Get-Command -module \"MCAS\" | Select-Object -Property Name | Format-Wide -Column 4\n",
- "Out-Display -input \"Type 'Get-Help <command> -Examples' to get help on any modules\""
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Configure Variables and store credentials in XML file"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "$tenantUri = \"domain.us3.portal.cloudappsecurity.com\""
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "$tenantName = ($tenantUri -replace \"https://\" | % {$_ -match \"(.*).portal.cloudappsecurity.com\"})\n",
- "if ($Matches[1]) {$tenantName = $Matches[1]} \n",
- "\n",
- "$path = New-Item -ItemType Directory -Force -Path \".\\Credentials\"\n",
- "$credentialPath = \".\\$($path.name)\\$tenantName.credential\"\n",
- "$credentialPath"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Import Credentials"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "## Import MCAS Credential or add credential if does not exist\n",
- "if( (Test-Path $credentialPath -PathType Leaf) ) {\n",
- " $CASCredential = Import-Clixml $credentialPath -ErrorAction SilentlyContinue\n",
- "} else {\n",
- " Get-MCASCredential -tenantUri $tenantUri -PassThru | Export-CliXml \".\\Credentials\\$($Matches[1]).credential\" -Force\n",
- " Write-Host \"Stored credentials in $credentialPath\"\n",
- "}"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Query MCAS REST API and determine if credentials exists"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "$MCASPolicies = Get-MCASPolicy\n",
- "Write-Host -Foreground green \"`n $($MCASPolicies.count) MCAS Policies Retrieved`n\"\n",
- "\n",
- "$MCASPolicies | Group-Object -Property policyType -NoElement | Sort-Object -Property Count -Descending | Select-Object Name,Count"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Pull all the Session policies"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "$filterPolicy = \"SESSION\"\n",
- "$MCASPolicies | Where-Object {$_.policyType -eq $filterPolicy} | Select-Object name | FT"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "$filterPolicyName = \"*DEMO*\"\n",
- "$MCASPolicies | Where-Object {$_.name -like $filterPolicyName} | FL"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": []
- }
- ],
- "metadata": {
- "kernelspec": {
- "display_name": ".NET (PowerShell)",
- "language": "PowerShell",
- "name": ".net-powershell"
- },
- "language_info": {
- "file_extension": ".ps1",
- "mimetype": "text/x-powershell",
- "name": "PowerShell",
- "pygments_lexer": "powershell",
- "version": "7.0"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 4
-}
diff --git a/Notebooks/PowerShell/Microsoft/Security/MCAS/README.md b/Notebooks/PowerShell/Microsoft/Security/MCAS/README.md
deleted file mode 100755
index c922f7a..0000000
--- a/Notebooks/PowerShell/Microsoft/Security/MCAS/README.md
+++ /dev/null
@@ -1,2 +0,0 @@
-
-[https://docs.microsoft.com/en-us/cloud-app-security/investigate-anomaly-alerts](MCAS Investigation Guide)
\ No newline at end of file
diff --git a/Notebooks/PowerShell/Microsoft/Security/MDATP/Alerts.ipynb b/Notebooks/PowerShell/Microsoft/Security/MDATP/Alerts.ipynb
deleted file mode 100755
index e7df279..0000000
--- a/Notebooks/PowerShell/Microsoft/Security/MDATP/Alerts.ipynb
+++ /dev/null
@@ -1,248 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "# Alerts\n",
- "\n",
- " Author: Jing Nghik\n",
- " Last Updated 2/9/2020\n",
- "\n",
- "Purpose: This notebook is used to add device's to a certain group based on the machine tag.\n",
- "\n",
- "## Requirements: \n",
- "\n",
- "### Scopes Required\n",
- "- Alert.Read.All\n",
- "- Alert.ReadWrite.All\n",
- "\n",
- "### A client AppID/Secret or Device Code Authentication\n",
- "[Proper MDATP API Token](https://docs.microsoft.com/en-us/windows/security/threat-protection/microsoft-defender-atp/exposed-apis-create-app-webapp)\n",
- " \n",
- " Microsoft Defender ATP exposes much of its data and actions through a set of programmatic APIs. Those APIs will help you automate work flows and innovate based on Microsoft Defender ATP capabilities."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Set Variables and Import required modules and credentials "
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 100,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "\n",
- "CommandType Name Version Source\n",
- "----------- ---- ------- ------\n",
- "Function Get-DecryptedStringUsingMasterPassword 0.0 pp-core\n",
- "Function Get-EncryptedStringUsingMasterPassword 0.0 pp-core\n",
- "Function Get-HashOfString 0.0 pp-core\n",
- "Function Get-MasterPassword 0.0 pp-core\n",
- "Function Get-StoredCredentials 0.0 pp-core\n",
- "Function Invoke-CheckCredentials 0.0 pp-core\n",
- "Function New-StoreCredentials 0.0 pp-core\n",
- "Function Get-MSGraphAuthToken 0.0 graph\n",
- "Function Invoke-GraphAuthentication 0.0 graph\n",
- "Function Invoke-MSGraphQuery 0.0 graph\n",
- "\n"
- ]
- }
- ],
- "source": [
- "## Change these if required\n",
- "$VerbosePreference = \"ignore\" ## Set to 'continue to get verbose output'\n",
- "$resource = \"https://api.securitycenter.windows.com\" ## resource Dont change since we want to query MDATP REST API Resource\n",
- "$grant_type = \"client_credentials\" ## This is using a device_code flow (supports: client_credentials, device_code)\n",
- "\n",
- "## This will run a script to import the required modules and credentials stored in the \"credential\" file\n",
- "$scriptPath = \"~/Notebooks/PowerShell/custom-modules/import.ps1\"; . $scriptPath # this will run the script"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Authenticate with Graph API and get access Token for MDATP Resource"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 101,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "\u001b[92m\n",
- "Authentication Parameters detected\u001b[0m\n",
- "Personal Access Token (PAT) grant_type\n",
- "\n",
- "----------------------------------------------------------------------------\n",
- "Authentiating with Microsoft Graph API using a Personal Access Token (PAT)\n",
- "\u001b[37mhttps://docs.microsoft.com/en-us/azure/storage/common/storage-auth-aad-app\u001b[0m\n",
- "----------------------------------------------------------------------------\n",
- "Requesting Token at https://login.microsoftonline.com/e4194ef7-b5d7-4db1-b7e9-a73af406f276/oauth2/token\n",
- "\u001b[92m\n",
- "\n",
- "Received Token!\u001b[0m\n",
- "\u001b[93mConnected and Access Token received and will expire 1612917824\u001b[0m\n",
- "\n",
- "Name Value\n",
- "---- -----\n",
- "Content-Type application/json\n",
- "Accept application/json\n",
- "Authorization Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImtpZCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyJ9.eyJhdWQiOiJodHRwczovL2FwaS5…\n",
- "\n"
- ]
- }
- ],
- "source": [
- "## Get a token if authenticates properly. \n",
- "\n",
- "$authParams = @{\n",
- " tenantId = $credentials.tenantId\n",
- " client_id = $credentials.client_id\n",
- " client_secret = $credentials.client_secret\n",
- " resource = $resource ## resource Dont change since we want to query MDATP REST API Resource\n",
- " grant_type = $grant_type ## This is using a device_code flow (supports: client_credentials, device_code)\n",
- " #scope = \"https://api.securitycenter.microsoft.com/Machine.ReadWrite.All\" ## set the scope\n",
- "};\n",
- "\n",
- "## this will authenticate with Graph API and token will be stored in variable.\n",
- "$token = (Invoke-GraphAuthentication -authParams $authParams)\n",
- "\n",
- "## This is the authentication header for REST API Call\n",
- "if ($token.access_token -ne $null) {\n",
- " $authHeader = @{ \n",
- " 'Content-Type' = 'application/json'\n",
- " Accept = 'application/json'\n",
- " Authorization = \"Bearer $($token.access_token)\" \n",
- " }\n",
- "}; $authHeader"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Gets the top 10 alerts"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 102,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "https://api.securitycenter.windows.com/api/alerts?top=10\n",
- "\n",
- "@odata.context value\n",
- "-------------- -----\n",
- "https://api.securitycenter.windows.com/api/$metadata#Alerts {}\n",
- "\n"
- ]
- }
- ],
- "source": [
- "## Set the path you want to query\n",
- "$endpoint = \"api/alerts?top=10\"\n",
- "$method = \"GET\"\n",
- "\n",
- "## The following commands will query the graph API and output the first 5 machines in table format\n",
- "$uri = \"$($resource)/$endpoint\"; $uri\n",
- "$Response = (Invoke-RestMethod -Method $method -Uri $uri -Headers $authHeader -ErrorAction Stop)\n",
- "$Response\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Create Alert by Reference \n",
- "- https://docs.microsoft.com/en-us/windows/security/threat-protection/microsoft-defender-atp/create-alert-by-reference"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 99,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "https://api.securitycenter.windows.com/api/alerts/CreateAlertByReference\n",
- "\u001b[91mInvoke-RestMethod: \n",
- "\u001b[96mLine |\n",
- "\u001b[96m 19 | \u001b[0m … Response = (\u001b[96mInvoke-RestMethod -Method $method -Uri $uri -Headers $aut\u001b[0m …\n",
- "\u001b[96m | \u001b[91m ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n",
- "\u001b[91m\u001b[96m | \u001b[91m{\"error\":{\"code\":\"InvalidInput\",\"message\":\"reportId is not in the correct format, expected long\",\"target\":\"9d072c8d-5a95-4fe1-8818-297ce855a812\"}}\u001b[0m\n",
- "{\n",
- " \"@odata.context\": \"https://api.securitycenter.windows.com/api/$metadata#Alerts\",\n",
- " \"value\": []\n",
- "}\n"
- ]
- }
- ],
- "source": [
- "$endpoint = \"api/alerts/CreateAlertByReference\"\n",
- "$method = \"POST\"\n",
- "\n",
- "$jsonBody = @\"\n",
- "{\n",
- " \"reportId\": \"{ReportId of the associated event}\",\n",
- " \"eventTime\": \"2018-08-03T16:45:21.7115183Z\",\n",
- " \"machineId\": \"cb5402466f9427f3ea03c81c872ff9be0ce4b03b\",\n",
- " \"severity\": \"Low\",\n",
- " \"title\": \"test alert\",\n",
- " \"description\": \"test alert\",\n",
- " \"recommendedAction\": \"test alert\",\n",
- " \"category\": \"SuspiciousActivity\"\n",
- "}\n",
- "\"@\n",
- "\n",
- "## The following commands will query the graph API and output the first 5 machines in table format\n",
- "$uri = \"$($resource)/$endpoint\"; $uri\n",
- "$Response = (Invoke-RestMethod -Method $method -Uri $uri -Headers $authHeader -body $jsonBody -ErrorAction Stop)\n",
- "($Response | ConvertTO-JSON)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": []
- }
- ],
- "metadata": {
- "kernelspec": {
- "display_name": ".NET (PowerShell)",
- "language": "PowerShell",
- "name": ".net-powershell"
- },
- "language_info": {
- "file_extension": ".ps1",
- "mimetype": "text/x-powershell",
- "name": "PowerShell",
- "pygments_lexer": "powershell",
- "version": "7.0"
- },
- "toc-autonumbering": true,
- "toc-showmarkdowntxt": true
- },
- "nbformat": 4,
- "nbformat_minor": 4
-}
diff --git a/Notebooks/PowerShell/Microsoft/Security/MDATP/Hunting - Simple Query.ipynb b/Notebooks/PowerShell/Microsoft/Security/MDATP/Hunting - Simple Query.ipynb
deleted file mode 100755
index 9ea8a1c..0000000
--- a/Notebooks/PowerShell/Microsoft/Security/MDATP/Hunting - Simple Query.ipynb
+++ /dev/null
@@ -1,168 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "# Rest API - Advanced Hunting Query\n",
- "\n",
- "\n",
- " \n",
- " Type | \n",
- " Title | \n",
- " Description | \n",
- " \n",
- " \n",
- " Documentation | \n",
- " Advanced Hunting API | \n",
- " This is the documentation that refers to what permissions is required and request examples you can use to query the MDATP API | \n",
- " \n",
- " "
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Pre-requisite"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Import required modules and credentials "
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "$VerbosePreference = \"ignore\" ## Set to 'continue to get verbose output'\n",
- "\n",
- "## This will run a script to import the required modules and credentials stored in the \"credential\" file\n",
- "$scriptPath = \"~/Notebooks/PowerShell/custom-modules/import.ps1\"; . $scriptPath # this will run the script"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Authenticate with Graph API and get access Token for MDATP Resource"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "## Get a token if authenticates properly. \n",
- "\n",
- "$authParams = @{\n",
- " tenantId = $credentials.tenantId\n",
- " client_id = $credentials.client_id\n",
- " client_secret = $credentials.client_secret\n",
- " resource = \"https://api.securitycenter.microsoft.com\" ## resource Dont change since we want to query MDATP REST API Resource\n",
- " grant_type = \"client_credentials\" ## This is using a device_code flow (supports: client_credentials, device_code)\n",
- " scope = \"https://api.securitycenter.microsoft.com/AdvancedQuery.ReadAll\" ## set the scope\n",
- "};\n",
- "\n",
- "## this will authenticate with Graph API and token will be stored in variable.\n",
- "$token = (Invoke-GraphAuthentication -authParams $authParams).access_token\n",
- "$token"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Put your Hunting Query here"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "## Enter your query here below $Query\n",
- "$body = (@{'Query' = @\"\n",
- "\n",
- "DeviceNetworkEvents \n",
- "| where InitiatingProcessFileName =~ 'powershell.exe'\n",
- "| limit 10\n",
- "\n",
- "\"@}) | ConvertTO-JSON;"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Query the MDATP API Grab report schema "
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "$URI = \"https://api.securitycenter.windows.com/api/advancedqueries/run\" ## This is the URL to query with the access token.\n",
- "$header = @{ ## This is the header\n",
- " 'Content-Type' = 'application/json'\n",
- " Accept = 'application/json'\n",
- " Authorization = \"Bearer $($token)\" }\n",
- "\n",
- "$Response = (Invoke-RestMethod -Method POST -Uri $URI -Headers $header -body $body -ErrorAction Stop)\n",
- "$Response"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Parse Results"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "## Filter by these columns\n",
- "$includeColumns = @('Timestamp','DeviceName','ActionType','RemoteIP')\n",
- "\n",
- "## These are the results\n",
- "$Response.Results | Select-Object -Property $includeColumns"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": []
- }
- ],
- "metadata": {
- "kernelspec": {
- "display_name": ".NET (PowerShell)",
- "language": "PowerShell",
- "name": ".net-powershell"
- },
- "language_info": {
- "file_extension": ".ps1",
- "mimetype": "text/x-powershell",
- "name": "PowerShell",
- "pygments_lexer": "powershell",
- "version": "7.0"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 4
-}
diff --git a/Notebooks/PowerShell/Microsoft/Security/MDATP/Machine - Device Tags.ipynb b/Notebooks/PowerShell/Microsoft/Security/MDATP/Machine - Device Tags.ipynb
deleted file mode 100644
index dea3c5d..0000000
--- a/Notebooks/PowerShell/Microsoft/Security/MDATP/Machine - Device Tags.ipynb
+++ /dev/null
@@ -1,264 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "# Add/Remove Machine to Device Groups based on Machine Tag\n",
- "\n",
- " Author: Jing Nghik\n",
- " Last Updated 6/23/2020\n",
- "\n",
- "Purpose: This notebook is used to add device's to a certain group based on the machine tag.\n",
- "\n",
- "## Requirements: \n",
- "\n",
- "[Machine groups already pre-configured by Device tag](https://docs.microsoft.com/en-us/windows/security/threat-protection/microsoft-defender-atp/machine-groups)\n",
- "\n",
- " You need to have the machine groups already configured that filter based on the device tag element.\n",
- "\n",
- "[Proper MDATP API Token](https://docs.microsoft.com/en-us/windows/security/threat-protection/microsoft-defender-atp/exposed-apis-create-app-webapp)\n",
- " \n",
- " Microsoft Defender ATP exposes much of its data and actions through a set of programmatic APIs. Those APIs will help you automate work flows and innovate based on Microsoft Defender ATP capabilities."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Import required modules and credentials "
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 4,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "\n",
- "CommandType Name Version Source\n",
- "----------- ---- ------- ------\n",
- "Function Get-DecryptedStringUsingMasterPassword 0.0 pp-core\n",
- "Function Get-EncryptedStringUsingMasterPassword 0.0 pp-core\n",
- "Function Get-HashOfString 0.0 pp-core\n",
- "Function Get-MasterPassword 0.0 pp-core\n",
- "Function Get-StoredCredentials 0.0 pp-core\n",
- "Function Invoke-CheckCredentials 0.0 pp-core\n",
- "Function New-StoreCredentials 0.0 pp-core\n",
- "Function Get-MSGraphAuthToken 0.0 graph\n",
- "Function Invoke-GraphAuthentication 0.0 graph\n",
- "Function Invoke-MSGraphQuery 0.0 graph\n",
- "\n"
- ]
- }
- ],
- "source": [
- "$VerbosePreference = \"ignore\" ## Set to 'continue to get verbose output'\n",
- "\n",
- "## This will run a script to import the required modules and credentials stored in the \"credential\" file\n",
- "$scriptPath = \"~/Notebooks/PowerShell/custom-modules/import.ps1\"; . $scriptPath # this will run the script"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Authenticate with Graph API and get access Token for MDATP Resource"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 5,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "\u001b[92m\n",
- "Authentication Parameters detected\u001b[0m\n",
- "Personal Access Token (PAT) grant_type\n",
- "\n",
- "----------------------------------------------------------------------------\n",
- "Authentiating with Microsoft Graph API using a Personal Access Token (PAT)\n",
- "\u001b[37mhttps://docs.microsoft.com/en-us/azure/storage/common/storage-auth-aad-app\u001b[0m\n",
- "----------------------------------------------------------------------------\n",
- "Requesting Token at https://login.microsoftonline.com/e4194ef7-b5d7-4db1-b7e9-a73af406f276/oauth2/token\n",
- "\u001b[92m\n",
- "\n",
- "Received Token!\u001b[0m\n",
- "\u001b[93mConnected and Access Token received and will expire 1612917847\u001b[0m\n",
- "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImtpZCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyJ9.eyJhdWQiOiJodHRwczovL2FwaS5zZWN1cml0eWNlbnRlci5taWNyb3NvZnQuY29tIiwiaXNzIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvZTQxOTRlZjctYjVkNy00ZGIxLWI3ZTktYTczYWY0MDZmMjc2LyIsImlhdCI6MTYxMjkxMzk0NywibmJmIjoxNjEyOTEzOTQ3LCJleHAiOjE2MTI5MTc4NDcsImFpbyI6IkUyWmdZUGltbGYwc3FmbGE4bytiRm8rZmhZZmVCUUE9IiwiYXBwaWQiOiJjZjg5YzdkYy1iNGFlLTQzMmItYjg4OS05MDk5YzkxYTI1NTciLCJhcHBpZGFjciI6IjEiLCJpZHAiOiJodHRwczovL3N0cy53aW5kb3dzLm5ldC9lNDE5NGVmNy1iNWQ3LTRkYjEtYjdlOS1hNzNhZjQwNmYyNzYvIiwib2lkIjoiYTgxNDI2NTctOWQzMi00YTFiLWJiYzctZjc2NjAyNmU3YjAxIiwicmgiOiIwLkFBQUE5MDRaNU5lMXNVMjM2YWM2OUFieWR0ekhpYy11dEN0RHVJbVFtY2thSlZkU0FBQS4iLCJyb2xlcyI6WyJNYWNoaW5lLklzb2xhdGUiLCJNYWNoaW5lLlNjYW4iLCJNYWNoaW5lLlJlYWRXcml0ZS5BbGwiLCJNYWNoaW5lLkxpdmVSZXNwb25zZSIsIlNlY3VyaXR5UmVjb21tZW5kYXRpb24uUmVhZC5BbGwiLCJNYWNoaW5lLlJlc3RyaWN0RXhlY3V0aW9uIiwiTWFjaGluZS5TdG9wQW5kUXVhcmFudGluZSIsIkFsZXJ0LlJlYWQuQWxsIiwiTWFjaGluZS5Db2xsZWN0Rm9yZW5zaWNzIiwiTWFjaGluZS5PZmZib2FyZCIsIlZ1bG5lcmFiaWxpdHkuUmVhZC5BbGwiLCJNYWNoaW5lLlJlYWQuQWxsIiwiQWxlcnQuUmVhZFdyaXRlLkFsbCIsIkFkdmFuY2VkUXVlcnkuUmVhZC5BbGwiXSwic3ViIjoiYTgxNDI2NTctOWQzMi00YTFiLWJiYzctZjc2NjAyNmU3YjAxIiwidGVuYW50X3JlZ2lvbl9zY29wZSI6Ik5BIiwidGlkIjoiZTQxOTRlZjctYjVkNy00ZGIxLWI3ZTktYTczYWY0MDZmMjc2IiwidXRpIjoicXFFYTJwN1g5RUd1X2EtVWhwUWVBQSIsInZlciI6IjEuMCJ9.R3831Z2ecjuZuybfRbbsZH1M6IyXkwA6Y5i1UadMP3VVSvH4_KTDOxbubxszAo52jAkQtRiWaFyS_T5CBt8OkQ42Xue5EC7Cjt0q5Xp6tWazDidJe8-4w8xGCvBqE6cxtoyQsql3mIaOBDjyzge7lR7TREp1_GgSnJpO4wXHOUEF5Iv3ogA73-Y5d2oT4C_Z3xzBuhhZ8iD0wpRqXL9d2ALjZHPrMxwstv8bnyWn4yhAJdIrBrfQI4YrSPHS7myWTUbXAQX7OhZwETPDNo7zgvJuhNOBFGG8rQD8Pd6tUYszOvhBUHVpbODuVKmzSnTrd1pDX8vTr_gndZ1JhjGpbg\n"
- ]
- }
- ],
- "source": [
- "## Get a token if authenticates properly. \n",
- "\n",
- "$authParams = @{\n",
- " tenantId = $credentials.tenantId\n",
- " client_id = $credentials.client_id\n",
- " client_secret = $credentials.client_secret\n",
- " resource = \"https://api.securitycenter.microsoft.com\" ## resource Dont change since we want to query MDATP REST API Resource\n",
- " grant_type = \"client_credentials\" ## This is using a device_code flow (supports: client_credentials, device_code)\n",
- " #scope = \"https://api.securitycenter.microsoft.com/Machine.ReadWrite.All\" ## set the scope\n",
- "};\n",
- "\n",
- "## this will authenticate with Graph API and token will be stored in variable.\n",
- "$token = (Invoke-GraphAuthentication -authParams $authParams).access_token\n",
- "$token"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Authenticate with Graph API and get access Token for MDATP Resource"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 6,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "\n",
- "id computerDnsName machineTags\n",
- "-- --------------- -----------\n",
- "cb5402466f9427f3ea03c81c872ff9be0ce4b03b w10-jingtoso {group1}\n",
- "\n"
- ]
- }
- ],
- "source": [
- "## This is the authentication header for REST API Call\n",
- "$authHeader = @{ \n",
- " 'Content-Type' = 'application/json'\n",
- " Accept = 'application/json'\n",
- " Authorization = \"Bearer $token\" \n",
- "}\n",
- "\n",
- "## The following commands will query the graph API and output the first 5 machines in table format\n",
- "$URI = \"https://api.securitycenter.windows.com/api/machines\"\n",
- "$Response = (Invoke-RestMethod -Method GET -Uri $URI -Headers $authHeader -body $body -ErrorAction Stop)\n",
- "$Response.value | Select-Object -First 5 | Select-Object @('id','computerDnsName','machineTags') | FT"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Identify machine, tag, and whether to add or remove the tag on the machine"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 7,
- "metadata": {},
- "outputs": [],
- "source": [
- "$machineId = \"cb5402466f9427f3ea03c81c872ff9be0ce4b03b\" ## Machine ID to add or remove device group\n",
- "$machineTag = \"boob\"\n",
- "$action = \"Add\" ## This can be add or remove"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Add/Remove machine based on above variables"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 8,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "{\n",
- " \"Action\": \"Add\",\n",
- " \"Value\": \"boob\"\n",
- "}\n",
- "https://api-us.securitycenter.windows.com/api/machines/cb5402466f9427f3ea03c81c872ff9be0ce4b03b/tags\n"
- ]
- }
- ],
- "source": [
- "####### Creates the json body ####################\n",
- "$jsonBody = @{\n",
- " Value = $machineTag\n",
- " Action = $action\n",
- "}\n",
- "$jsonBody = ($jsonbody | ConvertTo-JSON); $jsonBody\n",
- "\n",
- "####### Calls MDATP Rest API and either add or remove machine tag #################\n",
- "$URI = \"https://api-us.securitycenter.windows.com/api/machines/$machineId/tags\"; $URI\n",
- "$Response = Invoke-RestMethod -Method POST -Uri $URI -Headers $authHeader -body $jsonBody -ErrorAction Stop"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Get Machine list again to verify"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 9,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "\n",
- "id computerDnsName machineTags\n",
- "-- --------------- -----------\n",
- "cb5402466f9427f3ea03c81c872ff9be0ce4b03b w10-jingtoso {boob, group1}\n",
- "\n"
- ]
- }
- ],
- "source": [
- "$URI = \"https://api-us.securitycenter.windows.com/api/machines\"\n",
- "$Response = (Invoke-RestMethod -Method GET -Uri $URI -Headers $authHeader -body $body -ErrorAction Stop)\n",
- "$Response.value | Select-Object @('id','computerDnsName','machineTags') | FT"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": []
- }
- ],
- "metadata": {
- "kernelspec": {
- "display_name": ".NET (PowerShell)",
- "language": "PowerShell",
- "name": ".net-powershell"
- },
- "language_info": {
- "file_extension": ".ps1",
- "mimetype": "text/x-powershell",
- "name": "PowerShell",
- "pygments_lexer": "powershell",
- "version": "7.0"
- },
- "toc-autonumbering": true,
- "toc-showmarkdowntxt": true
- },
- "nbformat": 4,
- "nbformat_minor": 4
-}
diff --git a/Notebooks/PowerShell/Microsoft/Security/MDATP/Query using MDATP Github.ipynb b/Notebooks/PowerShell/Microsoft/Security/MDATP/Query using MDATP Github.ipynb
deleted file mode 100755
index 45db137..0000000
--- a/Notebooks/PowerShell/Microsoft/Security/MDATP/Query using MDATP Github.ipynb
+++ /dev/null
@@ -1,430 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "# MDATP - Use query from Github Repository"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 1,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/html": [
- "\r\n",
- "\r\n",
- " \r\n",
- " The below script needs to be able to find the current output cell; this is an easy method to get it.\r\n",
- " \r\n",
- " \r\n",
- " "
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- },
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "\n",
- "CommandType Name Version Source\n",
- "----------- ---- ------- ------\n",
- "Function Get-DecryptedStringUsingMasterPassword 0.0 pp-core\n",
- "Function Get-EncryptedStringUsingMasterPassword 0.0 pp-core\n",
- "Function Get-HashOfString 0.0 pp-core\n",
- "Function Get-MasterPassword 0.0 pp-core\n",
- "Function Get-StoredCredentials 0.0 pp-core\n",
- "Function Invoke-CheckCredentials 0.0 pp-core\n",
- "Function New-StoreCredentials 0.0 pp-core\n",
- "Function Get-MSGraphAuthToken 0.0 graph\n",
- "Function Invoke-GraphAuthentication 0.0 graph\n",
- "Function Invoke-MSGraphQuery 0.0 graph\n",
- "\n"
- ]
- }
- ],
- "source": [
- "## This will run a script to import the required modules and credentials stored in the \"credential\" file\n",
- "$scriptPath = \"~/Notebooks/PowerShell/custom-modules/import.ps1\"\n",
- ". $scriptPath # this will run the script"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Pull raw query from Github\n",
- "Be sure to provide the RAW Content and not a the github link of the source"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 2,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": []
- },
- "metadata": {},
- "output_type": "display_data"
- },
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "// This query finds network communication to specific URL\n",
- "// Please note that in line #7 it filters RemoteUrl using has operator, which looks for a \"whole term\" and runs faster.\n",
- "// Example: RemoteUrl has \"microsoft\" matches \"www.microsoft.com\" but not \"microsoftonline.com\"\n",
- "let partialRemoteUrlToDetect = \"microsoft.com\"; // Change this to a URL you'd like to find machines connecting to\n",
- "DeviceNetworkEvents \n",
- "| where Timestamp > ago(7d)\n",
- "and RemoteUrl has partialRemoteUrlToDetect // Can be changed to \"contains\" operator as explained above\n",
- "| project Timestamp, DeviceName, DeviceId, ReportId\n",
- "| top 100 by Timestamp desc\n",
- "\n"
- ]
- }
- ],
- "source": [
- "$rawGithubLink = \"https://raw.githubusercontent.com/microsoft/Microsoft-threat-protection-Hunting-Queries/master/Discovery/URL%20Detection.txt\"\n",
- "$Response = Invoke-WebRequest -Method GET -URI $rawGithubLink\n",
- "$body = (@{'Query' = $Response.Content}) | ConvertTO-JSON;\n",
- "$Response.Content"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Put your Hunting Query here"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 7,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "{\n",
- " \"Query\": \"// This query finds network communication to specific URL\\n// Please note that in line #7 it filters RemoteUrl using has operator, which looks for a \\\"whole term\\\" and runs faster.\\n// Example: RemoteUrl has \\\"microsoft\\\" matches \\\"www.microsoft.com\\\" but not \\\"microsoftonline.com\\\"\\nlet partialRemoteUrlToDetect = \\\"microsoft.com\\\"; // Change this to a URL you'd like to find machines connecting to\\nDeviceNetworkEvents \\n| where Timestamp > ago(7d)\\nand RemoteUrl has partialRemoteUrlToDetect // Can be changed to \\\"contains\\\" operator as explained above\\n| project Timestamp, DeviceName, DeviceId, ReportId\\n| top 100 by Timestamp desc\\n\"\n",
- "}\n"
- ]
- }
- ],
- "source": [
- "## Enter your query here below $Query\n",
- "$body = (@{'Query' = $Response.Content}) | ConvertTO-JSON;\n",
- "$body"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Query the MDATP API Grab report schema "
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 8,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "\n",
- "Name Value\n",
- "---- -----\n",
- "Content-Type application/json\n",
- "Authorization Bearer \n",
- "Accept application/json\n",
- "\u001b[91mInvoke-RestMethod: \n",
- "\u001b[96mLine |\n",
- "\u001b[96m 7 | \u001b[0m $Result = (\u001b[96mInvoke-RestMethod -Method POST -Uri $URI -Headers $authHea\u001b[0m …\n",
- "\u001b[96m | \u001b[91m ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n",
- "\u001b[91m\u001b[96m | \u001b[91mResponse status code does not indicate success: 401 (Unauthorized).\u001b[0m\n",
- "\n"
- ]
- }
- ],
- "source": [
- "$URI = \"https://api.securitycenter.windows.com/api/advancedqueries/run\"\n",
- "$authHeader = @{ \n",
- " 'Content-Type' = 'application/json'\n",
- " Accept = 'application/json'\n",
- " Authorization = \"Bearer $($tokenResponse.access_token)\" }\n",
- "$authHeader\n",
- "$Result = (Invoke-RestMethod -Method POST -Uri $URI -Headers $authHeader -body $body -ErrorAction Stop)\n",
- "$Result"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": []
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Parse report"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 7,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "\n",
- "Timestamp DeviceName ActionType RemoteIP\n",
- "--------- ---------- ---------- --------\n",
- "6/24/2020 7:12:32 PM win10-oobe-test \n",
- "6/24/2020 7:12:30 PM win10-oobe-test \n",
- "6/24/2020 7:12:29 PM win10-oobe-test \n",
- "6/24/2020 7:02:17 PM jingtoso-desktop1 \n",
- "6/24/2020 6:48:40 PM win10-oobe-test \n",
- "6/24/2020 6:40:39 PM win10-oobe-test \n",
- "6/24/2020 6:38:11 PM jingtoso-desktop1 \n",
- "6/24/2020 6:18:44 PM win10-oobe-test \n",
- "6/24/2020 6:18:24 PM win10-oobe-test \n",
- "6/24/2020 6:18:23 PM win10-oobe-test \n",
- "6/24/2020 6:18:16 PM win10-oobe-test \n",
- "6/24/2020 6:18:15 PM win10-oobe-test \n",
- "6/24/2020 6:13:13 PM win10-oobe-test \n",
- "6/24/2020 5:58:32 PM win10-oobe-test \n",
- "6/24/2020 5:57:34 PM win10-oobe-test \n",
- "6/24/2020 5:36:50 PM jing-lab \n",
- "6/24/2020 5:24:09 PM win10-oobe-test \n",
- "6/24/2020 5:10:50 PM win10-oobe-test \n",
- "6/24/2020 5:08:33 PM win10-oobe-test \n",
- "6/24/2020 5:07:47 PM jingtoso-desktop1 \n",
- "6/24/2020 4:55:09 PM jing-lab \n",
- "6/24/2020 4:48:30 PM jingtoso-desktop1 \n",
- "6/24/2020 4:43:13 PM win10-oobe-test \n",
- "6/24/2020 4:32:39 PM jingtoso-desktop1 \n",
- "6/24/2020 4:13:13 PM win10-oobe-test \n",
- "6/24/2020 4:02:11 PM win10-oobe-test \n",
- "6/24/2020 3:43:13 PM win10-oobe-test \n",
- "6/24/2020 3:43:13 PM win10-oobe-test \n",
- "6/24/2020 3:18:50 PM jingtoso-desktop1 \n",
- "6/24/2020 3:14:01 PM win10-oobe-test \n",
- "6/24/2020 3:13:13 PM win10-oobe-test \n",
- "6/24/2020 3:07:13 PM jingtoso-desktop1 \n",
- "6/24/2020 2:54:51 PM jingtoso-desktop1 \n",
- "6/24/2020 2:53:55 PM win10-oobe-test \n",
- "6/24/2020 2:46:51 PM jing-lab \n",
- "6/24/2020 2:21:51 PM win10-oobe-test \n",
- "6/24/2020 2:19:48 PM win10-oobe-test \n",
- "6/24/2020 2:04:42 PM jingtoso-desktop1 \n",
- "6/24/2020 1:34:37 PM jingtoso-desktop1 \n",
- "6/24/2020 1:19:58 PM jing-lab \n",
- "6/24/2020 1:14:32 PM win10-oobe-test \n",
- "6/24/2020 1:11:45 PM jing-lab \n",
- "6/24/2020 1:11:37 PM win10-oobe-test \n",
- "6/24/2020 12:47:34 PM win10-oobe-test \n",
- "6/24/2020 12:45:33 PM win10-oobe-test \n",
- "6/24/2020 12:43:12 PM win10-oobe-test \n",
- "6/24/2020 12:41:45 PM jing-lab \n",
- "6/24/2020 11:43:25 AM win10-oobe-test \n",
- "6/24/2020 11:43:12 AM win10-oobe-test \n",
- "6/24/2020 11:43:11 AM win10-oobe-test \n",
- "6/24/2020 11:40:17 AM jingtoso-desktop1 \n",
- "6/24/2020 11:33:24 AM win10-oobe-test \n",
- "6/24/2020 11:13:11 AM win10-oobe-test \n",
- "6/24/2020 10:43:11 AM win10-oobe-test \n",
- "6/24/2020 10:43:11 AM win10-oobe-test \n",
- "6/24/2020 10:42:38 AM jingtoso-desktop1 \n",
- "6/24/2020 10:23:33 AM win10-oobe-test \n",
- "6/24/2020 10:08:04 AM jingtoso-desktop1 \n",
- "6/24/2020 9:54:00 AM jingtoso-desktop1 \n",
- "6/24/2020 9:53:33 AM jing-lab \n",
- "6/24/2020 9:43:11 AM win10-oobe-test \n",
- "6/24/2020 9:41:20 AM jingtoso-desktop1 \n",
- "6/24/2020 9:37:39 AM jingtoso-desktop1 \n",
- "6/24/2020 9:36:55 AM win10-oobe-test \n",
- "6/24/2020 8:43:11 AM win10-oobe-test \n",
- "6/24/2020 8:28:45 AM win10-oobe-test \n",
- "6/24/2020 8:18:10 AM jing-lab \n",
- "6/24/2020 8:10:41 AM win10-oobe-test \n",
- "6/24/2020 7:56:39 AM win10-oobe-test \n",
- "6/24/2020 7:53:00 AM jingtoso-desktop1 \n",
- "6/24/2020 7:52:59 AM jingtoso-desktop1 \n",
- "6/24/2020 7:46:38 AM win10-oobe-test \n",
- "6/24/2020 7:06:30 AM win10-oobe-test \n",
- "6/24/2020 7:02:01 AM jingtoso-desktop1 \n",
- "6/24/2020 6:52:05 AM jingtoso-desktop1 \n",
- "6/24/2020 6:43:10 AM win10-oobe-test \n",
- "6/24/2020 6:42:26 AM win10-oobe-test \n",
- "6/24/2020 6:32:19 AM jing-lab \n",
- "6/24/2020 6:26:59 AM jingtoso-desktop1 \n",
- "6/24/2020 6:22:12 AM win10-oobe-test \n",
- "6/24/2020 6:13:10 AM win10-oobe-test \n",
- "6/24/2020 6:13:10 AM win10-oobe-test \n",
- "6/24/2020 6:02:01 AM jingtoso-desktop1 \n",
- "6/24/2020 5:52:48 AM jingtoso-desktop1 \n",
- "6/24/2020 5:43:10 AM win10-oobe-test \n",
- "6/24/2020 5:32:01 AM jingtoso-desktop1 \n",
- "6/24/2020 5:22:37 AM jingtoso-desktop1 \n",
- "6/24/2020 5:13:10 AM win10-oobe-test \n",
- "6/24/2020 5:11:37 AM jingtoso-desktop1 \n",
- "6/24/2020 5:08:05 AM jingtoso-desktop1 \n",
- "6/24/2020 5:08:03 AM jingtoso-desktop1 \n",
- "6/24/2020 5:04:11 AM win10-oobe-test \n",
- "6/24/2020 4:43:10 AM win10-oobe-test \n",
- "6/24/2020 4:36:36 AM win10-oobe-test \n",
- "6/24/2020 4:32:24 AM win10-oobe-test \n",
- "6/24/2020 4:32:06 AM win10-oobe-test \n",
- "6/24/2020 4:30:06 AM win10-oobe-test \n",
- "6/24/2020 4:27:07 AM jingtoso-desktop1 \n",
- "6/24/2020 4:26:05 AM win10-oobe-test \n",
- "6/24/2020 4:15:49 AM jingtoso-desktop1 \n",
- "\n"
- ]
- }
- ],
- "source": [
- "$includeColumns = @('Timestamp','DeviceName','ActionType','RemoteIP')\n",
- "$Result.Results | Select-Object -Property $includeColumns"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": []
- }
- ],
- "metadata": {
- "kernelspec": {
- "display_name": ".NET (PowerShell)",
- "language": "PowerShell",
- "name": ".net-powershell"
- },
- "language_info": {
- "file_extension": ".ps1",
- "mimetype": "text/x-powershell",
- "name": "PowerShell",
- "pygments_lexer": "powershell",
- "version": "7.0"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 4
-}
diff --git a/Notebooks/PowerShell/Microsoft/Security/MDATP/Security Recommendations.ipynb b/Notebooks/PowerShell/Microsoft/Security/MDATP/Security Recommendations.ipynb
deleted file mode 100644
index 869920a..0000000
--- a/Notebooks/PowerShell/Microsoft/Security/MDATP/Security Recommendations.ipynb
+++ /dev/null
@@ -1,199 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "# Get Vulerabilities\n",
- "\n",
- " Author: Jing Nghik\n",
- " Last Updated 2/9/2021\n",
- "\n",
- "Purpose: This notebook is an example to get Security recommendations\n",
- "\n",
- "## Requirements: \n",
- "\n",
- "### Scopes Required\n",
- "- Vulnerability.Read.All\n",
- "\n",
- "### A client AppID/Secret or Device Code Authentication\n",
- "[Proper MDATP API Token](https://docs.microsoft.com/en-us/windows/security/threat-protection/microsoft-defender-atp/exposed-apis-create-app-webapp)\n",
- " \n",
- " Microsoft Defender ATP exposes much of its data and actions through a set of programmatic APIs. Those APIs will help you automate work flows and innovate based on Microsoft Defender ATP capabilities."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Set Variables and Import required modules and credentials "
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 5,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "\n",
- "CommandType Name Version Source\n",
- "----------- ---- ------- ------\n",
- "Function Get-DecryptedStringUsingMasterPassword 0.0 pp-core\n",
- "Function Get-EncryptedStringUsingMasterPassword 0.0 pp-core\n",
- "Function Get-HashOfString 0.0 pp-core\n",
- "Function Get-MasterPassword 0.0 pp-core\n",
- "Function Get-StoredCredentials 0.0 pp-core\n",
- "Function Invoke-CheckCredentials 0.0 pp-core\n",
- "Function New-StoreCredentials 0.0 pp-core\n",
- "Function Get-MSGraphAuthToken 0.0 graph\n",
- "Function Invoke-GraphAuthentication 0.0 graph\n",
- "Function Invoke-MSGraphQuery 0.0 graph\n",
- "\n"
- ]
- }
- ],
- "source": [
- "## Change these if required\n",
- "$resource = \"https://api.securitycenter.windows.com\" ## resource Dont change since we want to query MDATP REST API Resource\n",
- "$grant_type = \"client_credentials\" ## This is using a device_code flow (supports: client_credentials, device_code)\n",
- "\n",
- "## Dont really need to change these unless necessary\n",
- "$VerbosePreference = \"ignore\" ## Set to 'continue to get verbose output'\n",
- "## This will run a script to import the required modules and credentials stored in the \"credential\" file\n",
- "$scriptPath = \"~/Notebooks/PowerShell/custom-modules/import.ps1\"; . $scriptPath # this will run the script"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Authenticate with Graph API and get access Token for MDATP Resource"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 6,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "\u001b[92m\n",
- "Authentication Parameters detected\u001b[0m\n",
- "Personal Access Token (PAT) grant_type\n",
- "\n",
- "----------------------------------------------------------------------------\n",
- "Authentiating with Microsoft Graph API using a Personal Access Token (PAT)\n",
- "\u001b[37mhttps://docs.microsoft.com/en-us/azure/storage/common/storage-auth-aad-app\u001b[0m\n",
- "----------------------------------------------------------------------------\n",
- "Requesting Token at https://login.microsoftonline.com/e4194ef7-b5d7-4db1-b7e9-a73af406f276/oauth2/token\n",
- "\u001b[92m\n",
- "\n",
- "Received Token!\u001b[0m\n",
- "\u001b[93mConnected and Access Token received and will expire 1612912469\u001b[0m\n",
- "\n",
- "Name Value\n",
- "---- -----\n",
- "Content-Type application/json\n",
- "Authorization Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhF…\n",
- "Accept application/json\n",
- "\n"
- ]
- }
- ],
- "source": [
- "## Get a token if authenticates properly. \n",
- "\n",
- "$authParams = @{\n",
- " tenantId = $credentials.tenantId\n",
- " client_id = $credentials.client_id\n",
- " client_secret = $credentials.client_secret\n",
- " resource = $resource ## resource Dont change since we want to query MDATP REST API Resource\n",
- " grant_type = $grant_type ## This is using a device_code flow (supports: client_credentials, device_code)\n",
- " #scope = \"https://api.securitycenter.microsoft.com/Machine.ReadWrite.All\" ## set the scope\n",
- "};\n",
- "\n",
- "## this will authenticate with Graph API and token will be stored in variable.\n",
- "$token = (Invoke-GraphAuthentication -authParams $authParams)\n",
- "\n",
- "## This is the authentication header for REST API Call\n",
- "if ($token.access_token -ne $null) {\n",
- " $authHeader = @{ \n",
- " 'Content-Type' = 'application/json'\n",
- " Accept = 'application/json'\n",
- " Authorization = \"Bearer $($token.access_token)\" \n",
- " }\n",
- "}; $authHeader"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Gets top 10 security recommendations"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 15,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "https://api.securitycenter.windows.com/api/recommendations\n",
- "\n",
- "id productName recommendationName\n",
- "-- ----------- ------------------ \n",
- "va-_-microsoft-_-windows_10 windows_10 Update Microsoft Windows 10 (OS and built-in applic…\n",
- "va-_-microsoft-_-.net_framework .net_framework Update Microsoft .net Framework \n",
- "sca-_-scid-2501 windows_10 Block all Office applications from creating child p…\n",
- "sca-_-scid-2502 windows_10 Block Office applications from creating executable …\n",
- "sca-_-scid-2504 windows_10 Block JavaScript or VBScript from launching downloa…\n",
- "sca-_-scid-2507 windows_10 Block executable files from running unless they mee…\n",
- "sca-_-scid-2510 windows_10 Block process creations originating from PSExec and…\n",
- "sca-_-scid-2511 windows_10 Block untrusted and unsigned processes that run fro…\n",
- "sca-_-scid-2512 windows_10 Block Office communication application from creatin…\n",
- "sca-_-scid-2513 windows_10 Block Adobe Reader from creating child processes \n",
- "\n"
- ]
- }
- ],
- "source": [
- "## Set the path you want to query\n",
- "$endpoint = \"api/recommendations\"\n",
- "$method = \"GET\"\n",
- "\n",
- "## The following commands will query the graph API and output the first 5 machines in table format\n",
- "$uri = \"$($resource)/$endpoint\"; $uri\n",
- "$Response = (Invoke-RestMethod -Method $method -Uri $uri -Headers $authHeader -ErrorAction Stop)\n",
- "\n",
- "## Converts Results into a table format\n",
- "$Response.value | Select -first 10 | FT"
- ]
- }
- ],
- "metadata": {
- "kernelspec": {
- "display_name": ".NET (PowerShell)",
- "language": "PowerShell",
- "name": ".net-powershell"
- },
- "language_info": {
- "file_extension": ".ps1",
- "mimetype": "text/x-powershell",
- "name": "PowerShell",
- "pygments_lexer": "powershell",
- "version": "7.0"
- },
- "toc-autonumbering": true,
- "toc-showmarkdowntxt": true
- },
- "nbformat": 4,
- "nbformat_minor": 4
-}
diff --git a/Notebooks/PowerShell/Microsoft/Security/MDATP/Vulnerabilities.ipynb b/Notebooks/PowerShell/Microsoft/Security/MDATP/Vulnerabilities.ipynb
deleted file mode 100644
index 729978b..0000000
--- a/Notebooks/PowerShell/Microsoft/Security/MDATP/Vulnerabilities.ipynb
+++ /dev/null
@@ -1,210 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "# Get Security Recommendations\n",
- "\n",
- " Author: Jing Nghik\n",
- " Last Updated 2/9/2021\n",
- "\n",
- "Purpose: This notebook is an example to get vulnerabilities\n",
- "\n",
- "## Requirements: \n",
- "\n",
- "### Scopes Required\n",
- "- SecurityRecommendation.Read\n",
- "- SecurityRecommendation.Read.All\n",
- "\n",
- "### A client AppID/Secret or Device Code Authentication\n",
- "[Proper MDATP API Token](https://docs.microsoft.com/en-us/windows/security/threat-protection/microsoft-defender-atp/exposed-apis-create-app-webapp)\n",
- " \n",
- " Microsoft Defender ATP exposes much of its data and actions through a set of programmatic APIs. Those APIs will help you automate work flows and innovate based on Microsoft Defender ATP capabilities."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Set Variables and Import required modules and credentials "
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 5,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "\n",
- "CommandType Name Version Source\n",
- "----------- ---- ------- ------\n",
- "Function Get-DecryptedStringUsingMasterPassword 0.0 pp-core\n",
- "Function Get-EncryptedStringUsingMasterPassword 0.0 pp-core\n",
- "Function Get-HashOfString 0.0 pp-core\n",
- "Function Get-MasterPassword 0.0 pp-core\n",
- "Function Get-StoredCredentials 0.0 pp-core\n",
- "Function Invoke-CheckCredentials 0.0 pp-core\n",
- "Function New-StoreCredentials 0.0 pp-core\n",
- "Function Get-MSGraphAuthToken 0.0 graph\n",
- "Function Invoke-GraphAuthentication 0.0 graph\n",
- "Function Invoke-MSGraphQuery 0.0 graph\n",
- "\n"
- ]
- }
- ],
- "source": [
- "## Change these if required\n",
- "$resource = \"https://api.securitycenter.windows.com\" ## resource Dont change since we want to query MDATP REST API Resource\n",
- "$grant_type = \"client_credentials\" ## This is using a device_code flow (supports: client_credentials, device_code)\n",
- "\n",
- "## Dont really need to change these unless necessary\n",
- "$VerbosePreference = \"ignore\" ## Set to 'continue to get verbose output'\n",
- "## This will run a script to import the required modules and credentials stored in the \"credential\" file\n",
- "$scriptPath = \"~/Notebooks/PowerShell/custom-modules/import.ps1\"; . $scriptPath # this will run the script"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Authenticate with Graph API and get access Token for MDATP Resource"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 6,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "\u001b[92m\n",
- "Authentication Parameters detected\u001b[0m\n",
- "Personal Access Token (PAT) grant_type\n",
- "\n",
- "----------------------------------------------------------------------------\n",
- "Authentiating with Microsoft Graph API using a Personal Access Token (PAT)\n",
- "\u001b[37mhttps://docs.microsoft.com/en-us/azure/storage/common/storage-auth-aad-app\u001b[0m\n",
- "----------------------------------------------------------------------------\n",
- "Requesting Token at https://login.microsoftonline.com/e4194ef7-b5d7-4db1-b7e9-a73af406f276/oauth2/token\n",
- "\u001b[92m\n",
- "\n",
- "Received Token!\u001b[0m\n",
- "\u001b[93mConnected and Access Token received and will expire 1612917907\u001b[0m\n",
- "\n",
- "Name Value\n",
- "---- -----\n",
- "Content-Type application/json\n",
- "Accept application/json\n",
- "Authorization Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImtpZCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyJ9.eyJhdWQiOiJodHRwczovL2FwaS5…\n",
- "\n"
- ]
- }
- ],
- "source": [
- "## Get a token if authenticates properly. \n",
- "\n",
- "$authParams = @{\n",
- " tenantId = $credentials.tenantId\n",
- " client_id = $credentials.client_id\n",
- " client_secret = $credentials.client_secret\n",
- " resource = $resource ## resource Dont change since we want to query MDATP REST API Resource\n",
- " grant_type = $grant_type ## This is using a device_code flow (supports: client_credentials, device_code)\n",
- " #scope = \"https://api.securitycenter.microsoft.com/Machine.ReadWrite.All\" ## set the scope\n",
- "};\n",
- "\n",
- "## this will authenticate with Graph API and token will be stored in variable.\n",
- "$token = (Invoke-GraphAuthentication -authParams $authParams)\n",
- "\n",
- "## This is the authentication header for REST API Call\n",
- "if ($token.access_token -ne $null) {\n",
- " $authHeader = @{ \n",
- " 'Content-Type' = 'application/json'\n",
- " Accept = 'application/json'\n",
- " Authorization = \"Bearer $($token.access_token)\" \n",
- " }\n",
- "}; $authHeader"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Gets top 10 security recommendations"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 7,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "URI: https://api.securitycenter.windows.com/api/vulnerabilities?top=10\n",
- "\n",
- "id name description severity exposedMachines\n",
- "-- ---- ----------- -------- ---------------\n",
- "CVE-2021-24082 CVE-2021-24082 Microsoft.PowerShell.Utility Module WDAC Security Feature Bypass Vulnerability Medium 1\n",
- "CVE-2021-24081 CVE-2021-24081 Microsoft Windows Codecs Library Remote Code Execution Vulnerability High 1\n",
- "CVE-2021-24096 CVE-2021-24096 Windows Kernel Elevation of Privilege Vulnerability High 1\n",
- "CVE-2021-24084 CVE-2021-24084 Windows Mobile Device Management Information Disclosure Vulnerability Medium 1\n",
- "CVE-2021-24093 CVE-2021-24093 Windows Graphics Component Remote Code Execution Vulnerability High 1\n",
- "CVE-2021-24088 CVE-2021-24088 Windows Local Spooler Remote Code Execution Vulnerability High 1\n",
- "CVE-2021-25195 CVE-2021-25195 Windows PKU2U Elevation of Privilege Vulnerability High 1\n",
- "CVE-2021-24091 CVE-2021-24091 Windows Camera Codec Pack Remote Code Execution Vulnerability High 1\n",
- "CVE-2021-24086 CVE-2021-24086 Windows TCP/IP Denial of Service Vulnerability High 1\n",
- "CVE-2021-24094 CVE-2021-24094 Windows TCP/IP Remote Code Execution Vulnerability Critical 1\n",
- "\n"
- ]
- }
- ],
- "source": [
- "## Set the path you want to query\n",
- "$endpoint = \"vulnerabilities?top=10\"\n",
- "$method = \"GET\"\n",
- "\n",
- "## The following commands will query the graph API and output the first 5 machines in table format\n",
- "$uri = \"$($resource)/api/$endpoint\"; Write-Host \"URI: $uri\"\n",
- "$Response = (Invoke-RestMethod -Method $method -Uri $uri -Headers $authHeader -ErrorAction Stop)\n",
- "\n",
- "## Filter results only for these columns\n",
- "$Response = ($Response.value | Select-Object @('id','name','description','severity','exposedMachines'))\n",
- "\n",
- "## Grab first 10 and convert results to table format\n",
- "$Response | Select -first 10 | FT"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": []
- }
- ],
- "metadata": {
- "kernelspec": {
- "display_name": ".NET (PowerShell)",
- "language": "PowerShell",
- "name": ".net-powershell"
- },
- "language_info": {
- "file_extension": ".ps1",
- "mimetype": "text/x-powershell",
- "name": "PowerShell",
- "pygments_lexer": "powershell",
- "version": "7.0"
- },
- "toc-autonumbering": true,
- "toc-showmarkdowntxt": true
- },
- "nbformat": 4,
- "nbformat_minor": 4
-}
diff --git a/Notebooks/PowerShell/Microsoft/Security/MTP/README.md b/Notebooks/PowerShell/Microsoft/Security/MTP/README.md
deleted file mode 100755
index e01af9c..0000000
--- a/Notebooks/PowerShell/Microsoft/Security/MTP/README.md
+++ /dev/null
@@ -1,11 +0,0 @@
-## Notebooks
-
-None available atm. Please contribute.
-
-## Helpful Documentation and Links
-
-Microsoft-threat-protection-Hunting-Queries - [Github @Microsoft](https://github.com/microsoft/Microsoft-threat-protection-Hunting-Queries)
- The purpose of this cheat sheet is to cover commonly used threat hunting queries that can be used with Microsoft Threat Protection. Microsoft Threat Protection has a threat hunting capability that is called Advance Hunting (AH). AH is based on Azure Kusto Query Language (KQL).
-
-Microsoft Threat Protection Advance Hunting Cheat Sheet - [Github @MiladMSFT](https://github.com/MiladMSFT/AdvHuntingCheatSheet)
- This repo contains sample queries for advanced hunting in Microsoft Threat Protection. With these sample queries, you can start to experience advanced hunting, including the types of data that it covers and the query language it supports. You can also explore a variety of attack techniques and how they may be surfaced through advanced hunting.
diff --git a/Notebooks/PowerShell/Shodan/Shodan - Check External IP for vuln.ipynb b/Notebooks/PowerShell/Shodan/Shodan - Check External IP for vuln.ipynb
deleted file mode 100755
index 69b6546..0000000
--- a/Notebooks/PowerShell/Shodan/Shodan - Check External IP for vuln.ipynb
+++ /dev/null
@@ -1,681 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "# Calling Shodan via Rest-API"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### First setup API Key\n",
- " Shodan REST API https://developer.shodan.io/ provided with the proper API key"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 272,
- "metadata": {},
- "outputs": [],
- "source": [
- "$APIKey = \"xxxxxxxYMDeqVS3HxxxxxxOi18yxxxxx\" ## API Key obtained from Shodan\n",
- "$credentialPath = \".\\credentials\\shodan.credential\" ## where to store credentials"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### Import Shodan PS Module"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 1,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/html": [
- "\r\n",
- "\r\n",
- " \r\n",
- " The below script needs to be able to find the current output cell; this is an easy method to get it.\r\n",
- " \r\n",
- " \r\n",
- " "
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- },
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "\n",
- "Get-ShodanAPIInfo Get-ShodanDNSResolve Get-ShodanDNSReverse Get-ShodanHostService\n",
- "Get-ShodanMyIP Get-ShodanService Measure-ShodanExploit Measure-ShodanHost\n",
- "Read-ShodanAPIKey Search-ShodanExploit Search-ShodanHost Set-ShodanAPIKey\n",
- "\n"
- ]
- },
- {
- "data": {
- "text/html": [
- "Type 'Get-Help <command> -Examples' to get help on any modules"
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- }
- ],
- "source": [
- "$host.UI.RawUI.BufferSize = [System.Management.Automation.Host.Size]::new(200, 50) ## Corrects the output\n",
- "Import-Module \".\\modules\\shodan.psm1\" -force\n",
- "\n",
- "# Grabbing commands available\n",
- "Get-Command -module \"shodan\" | Select-Object -Property Name | Format-Wide -Column 4\n",
- "Out-Display -input \"Type 'Get-Help <command> -Examples' to get help on any modules\""
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "# first build credentials"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": []
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/html": [
- "\r\n",
- "\r\n",
- " \r\n",
- " The below script needs to be able to find the current output cell; this is an easy method to get it.\r\n",
- " \r\n",
- " \r\n",
- " "
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- }
- ],
- "source": [
- "# Converts the API key to a SecureString\n",
- "if (!$credentialPath) {$credentialPath =\".\\credentials\\shodan.credential\"}\n",
- "if (!$APIKey) {$APIKey = Read-host \"No APIKey provided, please enter Shodan API Key you got: \"}\n",
- "$SecureKeyString = ConvertTo-SecureString -String $APIKey -AsPlainText -Force\n",
- "\n",
- "# Get a master password used to encrypt and decrypt Key\n",
- "Write-Host -Foreground cyan \"`nPlease enter a master password that will be used to encrypt/decrypt this API Key stored locally\";\n",
- "$MasterPassword = Read-Host -AsSecureString\n",
- "$Credentials = New-Object System.Management.Automation.PSCredential -ArgumentList 'user', $MasterPassword\n",
- "\n",
- "# Generate a random secure Salt\n",
- "$SaltBytes = New-Object byte[] 32\n",
- "[Security.Cryptography.RNGCryptoServiceProvider]::Create().GetBytes($SaltBytes)\n",
- "\n",
- "# This takes the master password and salt it\n",
- "# Rfc2898DeriveBytes takes a password, a salt, and an iteration count, and then generates keys through calls to the GetBytes method.\n",
- "$Rfc2898Deriver = New-Object System.Security.Cryptography.Rfc2898DeriveBytes -ArgumentList $Credentials.GetNetworkCredential().Password, $SaltBytes\n",
- "$KeyBytes = $Rfc2898Deriver.GetBytes(32)\n",
- "\n",
- "# This commands uses Advanced Encryption Standard (AES) algorith\n",
- "# It will convert the secure string stored in the $SecureKeyString variable to an encrypted standard string using this 256-bit salt key.\n",
- "# The resulting encrypted standard string is stored in the $StandardString variable.\n",
- "$EncryptedString = $SecureKeyString | ConvertFrom-SecureString -key $KeyBytes\n",
- "Write-Host -ForegroundColor Cyan \"Encrypted String: \" -noNewLine; $EncryptedString\n",
- "\n",
- "Write-Host -Message \"Saving the credentials to configuration file $credentialPath\"\n",
- "\n",
- "$credXML = @{\n",
- " api_key = $EncryptedString\n",
- " salt = $SaltBytes }\n",
- " \n",
- "if ( (Test-Path $credentialPath) -and ($APIKey) ) {\n",
- "\n",
- " $title = \"Credential file already detected in $credentialPath`n\"\n",
- " $question = \"Do you want to replace it?\"\n",
- "\n",
- " $choices = New-Object Collections.ObjectModel.Collection[Management.Automation.Host.ChoiceDescription]\n",
- " $choices.Add((New-Object Management.Automation.Host.ChoiceDescription -ArgumentList '&Yes'))\n",
- " $choices.Add((New-Object Management.Automation.Host.ChoiceDescription -ArgumentList '&No'))\n",
- "\n",
- " $decision = $Host.UI.PromptForChoice($title, $question, $choices, 1)\n",
- " if ($decision -eq 0) {\n",
- " Write-Host -ForegroundColor Green \"`nConfirmed\"\n",
- " $credXML | Export-CliXml \"$storagePath\\shodan.credential\" -Force\n",
- " } else {\n",
- " Write-Host -ForegroundColor Red \"`nCancelled, file won't be replaced.\"\n",
- " }\n",
- "} \n",
- "\n",
- "$credXML = Import-Clixml $credentialPath -ErrorAction SilentlyContinue"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 1,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/html": [
- "\r\n",
- "\r\n",
- " \r\n",
- " The below script needs to be able to find the current output cell; this is an easy method to get it.\r\n",
- " \r\n",
- " \r\n",
- " "
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- },
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "\u001b[96m\n",
- "Please enter a master password that will be used to encrypt/decrypt this API Key stored locally\u001b[0m\n"
- ]
- },
- {
- "name": "stdin",
- "output_type": "stream",
- "text": [
- " ·········\n"
- ]
- },
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "\u001b[91mNew-Object: \n",
- "\u001b[96mLine |\n",
- "\u001b[96m 8 | \u001b[0m … 98Deriver = \u001b[96mNew-Object System.Security.Cryptography.Rfc2898DeriveByte\u001b[0m …\n",
- "\u001b[96m | \u001b[91m ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n",
- "\u001b[91m\u001b[96m | \u001b[91mException calling \".ctor\" with \"2\" argument(s): \"Value cannot be null. (Parameter 'salt')\"\u001b[0m\n",
- "\u001b[91mInvalidOperation: \n",
- "\u001b[96mLine |\n",
- "\u001b[96m 9 | \u001b[0m \u001b[96m$KeyBytes = $Rfc2898Deriver.GetBytes(32)\u001b[0m\n",
- "\u001b[96m | \u001b[91m ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n",
- "\u001b[91m\u001b[96m | \u001b[91mYou cannot call a method on a null-valued expression.\u001b[0m\n",
- "\u001b[91mConvertTo-SecureString: \n",
- "\u001b[96mLine |\n",
- "\u001b[96m 11 | \u001b[0m $SecString = ConvertTo-SecureString \u001b[96m$($credXML.api_key)\u001b[0m -Key $KeyByte …\n",
- "\u001b[96m | \u001b[91m ~~~~~~~~~~~~~~~~~~~\n",
- "\u001b[91m\u001b[96m | \u001b[91mCannot bind argument to parameter 'String' because it is null.\u001b[0m\n",
- "\u001b[91mConvertFrom-SecureString: \n",
- "\u001b[96mLine |\n",
- "\u001b[96m 12 | \u001b[0m $APIKey = ($SecString | \u001b[96mConvertFrom-SecureString -AsPlainText\u001b[0m)\n",
- "\u001b[96m | \u001b[91m ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n",
- "\u001b[91m\u001b[96m | \u001b[91mCannot bind argument to parameter 'SecureString' because it is null.\u001b[0m\n"
- ]
- }
- ],
- "source": [
- "#Get a master password used to encrypt and decrypt Key\n",
- "Write-Host -Foreground cyan \"`nPlease enter a master password that will be used to encrypt/decrypt this API Key stored locally\";\n",
- "$MasterPassword = Read-Host -AsSecureString\n",
- "\n",
- "$SaltBytes = $credXML.salt\n",
- "$Credentials = New-Object System.Management.Automation.PSCredential -ArgumentList 'user', $MasterPassword\n",
- "\n",
- "$Rfc2898Deriver = New-Object System.Security.Cryptography.Rfc2898DeriveBytes -ArgumentList $Credentials.GetNetworkCredential().Password, $SaltBytes\n",
- "$KeyBytes = $Rfc2898Deriver.GetBytes(32)\n",
- "\n",
- "$SecString = ConvertTo-SecureString $($credXML.api_key) -Key $KeyBytes \n",
- "$APIKey = ($SecString | ConvertFrom-SecureString -AsPlainText)\n",
- "\n",
- "if ($APIKey) {\n",
- " Write-Host -ForegroundColor green \"`nCredentials have successfully been imported from $credentialPath\"\n",
- "}"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 67,
- "metadata": {},
- "outputs": [],
- "source": [
- "if (!(Test-Path -Path \"$storagePath\")) {\n",
- " Write-Verbose -Message 'Seems this is the first time the config has been set.'\n",
- " Write-Verbose -Message \"Creating folder $storagePath\"\n",
- " New-Item -ItemType directory -Path $storagePath | Out-Null\n",
- "}\n",
- "\n",
- "Write-Verbose -Message \"Saving the information to configuration file $storagePath\\$APIKey\"\n",
- "\"$($EncryptedString)\" | Set-Content \"$storagePath\\api.key\" -Force\n",
- "Set-Content -Value $SaltBytes -AsByteStream -Path \"$($storagePath)\\$saltname\" -Force"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 40,
- "metadata": {},
- "outputs": [],
- "source": [
- "$SecureKeyString = ConvertTo-SecureString -String $APIKey -AsPlainText -Force\n",
- "$Credentials = New-Object System.Management.Automation.PSCredential -ArgumentList 'user', $MasterPassword"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Setup Variables"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### Import required modules"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### Enter a domain name or IP address to check\n",
- "- Example: \"jingtoso.com\" or \"52.1.4.1\""
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 281,
- "metadata": {},
- "outputs": [],
- "source": [
- "$query = \"entergy.com\""
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### Logic to determine if its contains letters or not and resolve if it does."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### Query by Hostname or IP"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 288,
- "metadata": {},
- "outputs": [],
- "source": [
- "$hostIP = \"4.2.2.1\"\n",
- "$URI = \"https://api.shodan.io/shodan/host/$($hostIP)?key=$($APIKey)\"\n",
- "\n",
- "$discovery = Invoke-RestMethod -Method GET -Uri $URI"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### Parse Data"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 289,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "67240449 udp 53 \n"
- ]
- }
- ],
- "source": [
- "$discovery.data | ForEach -process { \n",
- " Write-Host $_.ip, $_.info, $_.transport, $_.port, $_.product\n",
- "} "
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 290,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "\n",
- "hash : -103662790\n",
- "ip : 67240449\n",
- "isp : Level 3 Communications\n",
- "transport : udp\n",
- "data : Version: recursive-main/20717463\n",
- " Recursion: enabled\n",
- " Resolver name: cns2.lax1.Level3.net\n",
- " Resolver ID: pubntp1.lax1.Level3.net\n",
- "asn : AS3356\n",
- "port : 53\n",
- "hostnames : {a.resolvers.level3.net}\n",
- "location : @{city=; region_code=; area_code=; longitude=-97.822; country_code3=; latitude=37.751; postal_code=; dma_code=; country_code=US; country_name=United States}\n",
- "dns : @{software=Version: recursive-main/20717463; recursive=True; resolver_id=pubntp1.lax1.Level3.net; resolver_hostname=cns2.lax1.Level3.net}\n",
- "timestamp : 6/18/2020 5:10:21 AM\n",
- "domains : {level3.net}\n",
- "org : Level 3 Communications\n",
- "os : \n",
- "_shodan : @{crawler=b0f0de701beef55d9f52a22b2c071d0ea384bc26; ptr=True; id=7781495f-a833-4c70-aaa7-4e34b4df493c; module=dns-udp; options=}\n",
- "opts : @{raw=34ef818000010001000000000776657273696f6e0462696e640000100003c00c001000030000000100212056657273696f6e3a207265637572736976652d6d61696e2f3230373137343633}\n",
- "ip_str : 4.2.2.1\n",
- "\n",
- "\n"
- ]
- }
- ],
- "source": [
- "$discovery.data | ForEach -process { \n",
- " $_ \n",
- "} "
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": []
- }
- ],
- "metadata": {
- "kernelspec": {
- "display_name": ".NET (PowerShell)",
- "language": "PowerShell",
- "name": ".net-powershell"
- },
- "language_info": {
- "file_extension": ".ps1",
- "mimetype": "text/x-powershell",
- "name": "PowerShell",
- "pygments_lexer": "powershell",
- "version": "7.0"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 4
-}
diff --git a/Notebooks/PowerShell/Shodan/modules/shodan.psm1 b/Notebooks/PowerShell/Shodan/modules/shodan.psm1
deleted file mode 100755
index 5b4ce51..0000000
--- a/Notebooks/PowerShell/Shodan/modules/shodan.psm1
+++ /dev/null
@@ -1,1730 +0,0 @@
-# .ExternalHelp Posh-Shodan.Help.xml
-function Get-ShodanAPIInfo
-{
- [CmdletBinding(DefaultParameterSetName = 'Direct')]
- Param
- (
- # Shodan developer API key
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Proxy')]
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Direct')]
- [string]
- $APIKey,
-
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Proxy')]
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Direct')]
- [string]
- $CertificateThumbprint,
-
- [Parameter(Mandatory=$true,
- ParameterSetName = 'Proxy')]
- [string]
- $Proxy,
-
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Proxy')]
- [Management.Automation.PSCredential]
- $ProxyCredential,
-
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Proxy')]
- [Switch]
- $ProxyUseDefaultCredentials
- )
-
- Begin
- {
- if (!(Test-Path variable:Global:ShodanAPIKey ) -and !($APIKey))
- {
- throw 'No Shodan API Key has been specified or set.'
- }
- elseif ((Test-Path variable:Global:ShodanAPIKey ) -and !($APIKey))
- {
- $APIKey = $Global:ShodanAPIKey
- }
-
- # Start building parameters for REST Method invokation.
- $Params = @{}
- $Params.add('Body', @{'key'= $APIKey})
- $Params.add('Method', 'Get')
- $Params.add('Uri',[uri]'https://api.shodan.io/api-info')
-
- # Check if connection will be made thru a proxy.
- if ($PsCmdlet.ParameterSetName -eq 'Proxy')
- {
- $Params.Add('Proxy', $Proxy)
-
- if ($ProxyCredential)
- {
- $Params.Add('ProxyCredential', $ProxyCredential)
- }
-
- if ($ProxyUseDefaultCredentials)
- {
- $Params.Add('ProxyUseDefaultCredentials', $ProxyUseDefaultCredentials)
- }
- }
-
- # Check if we will be doing certificate pinning by checking the certificate thumprint.
- if ($CertificateThumbprint)
- {
- $Params.Add('CertificateThumbprint', $CertificateThumbprint)
- }
- }
- Process
- {
- $ReturnedObject = Invoke-RestMethod @Params
- if ($ReturnedObject)
- {
- $ReturnedObject.pstypenames.insert(0,'Shodan.APIKey.Info')
- $ReturnedObject
- }
- }
- End
- {
- }
-}
-
-# .ExternalHelp Posh-Shodan.Help.xml
-function Get-ShodanService
-{
- [CmdletBinding(DefaultParameterSetName = 'Direct')]
- Param
- (
- # Shodan developer API key
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Proxy')]
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Direct')]
- [string]
- $APIKey,
-
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Proxy')]
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Direct')]
- [string]
- $CertificateThumbprint,
-
- [Parameter(Mandatory=$true,
- ParameterSetName = 'Proxy')]
- [string]
- $Proxy,
-
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Proxy')]
- [Management.Automation.PSCredential]
- $ProxyCredential,
-
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Proxy')]
- [Switch]
- $ProxyUseDefaultCredentials
- )
-
- Begin
- {
- if (!(Test-Path variable:Global:ShodanAPIKey ) -and !($APIKey))
- {
- throw 'No Shodan API Key has been specified or set.'
- }
- elseif ((Test-Path variable:Global:ShodanAPIKey ) -and !($APIKey))
- {
- $APIKey = $Global:ShodanAPIKey
- }
-
- # Start building parameters for REST Method invokation.
- $Params = @{}
- $Params.add('Body', @{'key'= $APIKey})
- $Params.add('Method', 'Get')
- $Params.add('Uri',[uri]'https://api.shodan.io/shodan/services')
-
- # Check if connection will be made thru a proxy.
- if ($PsCmdlet.ParameterSetName -eq 'Proxy')
- {
- $Params.Add('Proxy', $Proxy)
-
- if ($ProxyCredential)
- {
- $Params.Add('ProxyCredential', $ProxyCredential)
- }
-
- if ($ProxyUseDefaultCredentials)
- {
- $Params.Add('ProxyUseDefaultCredentials', $ProxyUseDefaultCredentials)
- }
- }
-
- # Check if we will be doing certificate pinning by checking the certificate thumprint.
- if ($CertificateThumbprint)
- {
- $Params.Add('CertificateThumbprint', $CertificateThumbprint)
- }
- }
- Process
- {
- $ReturnedObject = Invoke-RestMethod @Params
- if ($ReturnedObject)
- {
- $ReturnedObject.pstypenames.insert(0,'Shodan.Services')
- $ReturnedObject
- }
- }
- End
- {
- }
-}
-
-# .ExternalHelp Posh-Shodan.Help.xml
-function Get-ShodanHostService
-{
- [CmdletBinding(DefaultParameterSetName = 'Direct')]
- Param
- (
- # Shodan developer API key
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Proxy')]
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Direct')]
- [string]
- $APIKey,
-
- [Parameter(Mandatory=$true,
- ParameterSetName = 'Proxy')]
- [Parameter(Mandatory=$true,
- ParameterSetName = 'Direct')]
- [string]
- $IPAddress,
-
- # All historical banners should be returned.
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Proxy')]
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Direct')]
- [switch]
- $History,
-
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Proxy')]
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Direct')]
- [string]
- $CertificateThumbprint,
-
- [Parameter(Mandatory=$true,
- ParameterSetName = 'Proxy')]
- [string]
- $Proxy,
-
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Proxy')]
- [Management.Automation.PSCredential]
- $ProxyCredential,
-
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Proxy')]
- [Switch]
- $ProxyUseDefaultCredentials
- )
-
- Begin
- {
- if (!(Test-Path variable:Global:ShodanAPIKey ) -and !($APIKey))
- {
- throw 'No Shodan API Key has been specified or set.'
- }
- elseif ((Test-Path variable:Global:ShodanAPIKey ) -and !($APIKey))
- {
- $APIKey = $Global:ShodanAPIKey
- }
-
- $Body = @{'key'= $APIKey; 'ip' = $IPAddress}
-
- if ($History)
- {
- $Body.add('history','True')
- }
-
- # Start building parameters for REST Method invokation.
- $Params = @{}
- $Params.add('Body', $Body)
- $Params.add('Method', 'Get')
- $Params.add('Uri',[uri]"https://api.shodan.io/shodan/host/$($IPAddress)")
-
- # Check if connection will be made thru a proxy.
- if ($PsCmdlet.ParameterSetName -eq 'Proxy')
- {
- $Params.Add('Proxy', $Proxy)
-
- if ($ProxyCredential)
- {
- $Params.Add('ProxyCredential', $ProxyCredential)
- }
-
- if ($ProxyUseDefaultCredentials)
- {
- $Params.Add('ProxyUseDefaultCredentials', $ProxyUseDefaultCredentials)
- }
- }
-
- # Check if we will be doing certificate pinning by checking the certificate thumprint.
- if ($CertificateThumbprint)
- {
- $Params.Add('CertificateThumbprint', $CertificateThumbprint)
- }
- }
- Process
- {
- $ReturnedObject = Invoke-RestMethod @Params
- if ($ReturnedObject)
- {
- $ReturnedObject.pstypenames.insert(0,'Shodan.Host.Info')
- $ReturnedObject
- }
- }
- End
- {
- }
-}
-
-# .ExternalHelp Posh-Shodan.Help.xml
-function Search-ShodanHost
-{
- [CmdletBinding(DefaultParameterSetName = 'Direct')]
- Param
- (
- # Shodan developer API key
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Proxy')]
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Direct')]
- [string]
- $APIKey,
-
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Proxy')]
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Direct')]
- [string]
- $CertificateThumbprint,
-
- [Parameter(Mandatory=$true,
- ParameterSetName = 'Proxy')]
- [string]
- $Proxy,
-
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Proxy')]
- [Management.Automation.PSCredential]
- $ProxyCredential,
-
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Proxy')]
- [Switch]
- $ProxyUseDefaultCredentials,
-
- # Text to query for.
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Proxy')]
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Direct')]
- [string]
- $Query = '',
-
- # Find devices located in the given city. It's best combined with the
- # 'Country' filter to make sure you get the city in the country you
- # want (city names are not always unique).
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Proxy')]
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Direct')]
- [string]
- $City,
-
- # Narrow results down by country.
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Proxy')]
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Direct')]
- [string]
- $Country,
-
- # Latitude and longitude.
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Proxy')]
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Direct')]
- [string]
- $Geo,
-
- # Search for hosts that contain the value in their hostname.
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Proxy')]
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Direct')]
- [string]
- $Hostname,
-
- # Limit the search results to a specific IP or subnet. It uses CIDR
- # notation to designate the subnet range.
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Proxy')]
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Direct')]
- [string]
- $Net,
-
- # Specific operating systems. Common possible values are: windows,
- # linux and cisco.
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Proxy')]
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Direct')]
- [string]
- $OS,
-
- # Search the HTML of the website for the given value.
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Proxy')]
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Direct')]
- [string]$HTML,
-
- # Find devices based on the upstream owner of the IP netblock.
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Proxy')]
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Direct')]
- [string]$ISP,
-
- # The network link type. Possible values are: "Ethernet or modem",
- # "generic tunnel or VPN", "DSL", "IPIP or SIT", "SLIP", "IPSec or
- # "GRE", "VLAN", "jumbo Ethernet", "Google", "GIF", "PPTP", "loopback",
- # "AX.25 radio modem".
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Proxy')]
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Direct')]
- [ValidateSet( 'Ethernet or modem', 'generic tunnel or VPN', 'DSL',
- 'IPIP or SIT', 'SLIP', 'IPSec or GRE', 'VLAN', 'jumbo Ethernet',
- 'Google', 'GIF', 'PPTP', 'loopback', 'AX.25 radio modem')]
- [string[]]$Link,
-
- #Find NTP servers that had the given IP in their monlist.
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Proxy')]
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Direct')]
- [string]$NTP_IP,
-
- # Find NTP servers that return the given number of IPs in the initial monlist response.
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Proxy')]
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Direct')]
- [string]$NTP_IP_Count,
-
- # Find NTP servers that had IPs with the given port in their monlist.
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Proxy')]
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Direct')]
- [int]$NTP_Port,
-
- # Whether or not more IPs were available for the given NTP server.
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Proxy')]
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Direct')]
- [switch]$NTP_More,
-
- # Find devices based on the owner of the IP netblock.
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Proxy')]
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Direct')]
- [string]$Org,
-
- # Filter using the name of the software/ product; ex: product:Apache
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Proxy')]
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Direct')]
- [string]$Product,
-
- # Filter the results to include only products of the given version; ex: product:apache version:1.3.37
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Proxy')]
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Direct')]
- [string]$Version,
-
- # Search the title of the website.
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Proxy')]
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Direct')]
- [string]$Title,
-
- # Port number to narrow the search to specific services.
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Proxy')]
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Direct')]
- [string]$Port,
-
- # Limit search for data that was collected before the given date in
- # format day/month/year.
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Proxy')]
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Direct')]
- [string]$Before,
-
- # Limit search for data that was collected after the given date in
- # format day/month/year.
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Proxy')]
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Direct')]
- [string]$After,
-
- # The page number to page through results 100 at a time. Overrides the
- # "offset" and "limit" parameters if they were provided (default: 1)
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Proxy')]
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Direct')]
- [int]$Page,
-
- # The positon from which the search results should be returned (default: 0)
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Proxy')]
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Direct')]
- [int]$Offset,
-
- # The number of results to be returned default(100)
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Proxy')]
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Direct')]
- [int]$Limit,
-
- # True or False; whether or not to truncate some of the larger fields (default: True)
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Proxy')]
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Direct')]
- [bool]$Minify = $true,
-
- # A comma-separated list of properties to get summary information on. Property names
- # can also be in the format of "property:count", where "count" is the number of facets
- # that will be returned for a property (i.e. "country:100" to get the top 100 countries
- # for a search query).
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Proxy')]
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Direct')]
- [string]$Facets
-
- )
-
- Begin
- {
- if (!(Test-Path variable:Global:ShodanAPIKey ) -and !($APIKey))
- {
- throw 'No Shodan API Key has been specified or set.'
- }
- elseif ((Test-Path -Path variable:Global:ShodanAPIKey ) -and !($APIKey))
- {
- $APIKey = $Global:ShodanAPIKey
- }
-
- # Create the query string to execute.
- if ($City) {$Query += " city:'$($City.Trim())'"}
-
- if ($Country) {$Query += " country_name:`'$($Country.Trim())`'"}
-
- if ($Geo) {$Query += " geo:$($Geo.Trim())"}
-
- if ($Hostname) {$Query += " hostname:$($Hostname.Trim())"}
-
- if ($Net) {$Query += " net:$($Net.Trim())"}
-
- if ($OS) {$Query += " os:$($OS.Trim())"}
-
- if ($Port) {$Query += " port:$($Port.Trim())"}
-
- if ($Before) {$Query += " before:$($Before.Trim())"}
-
- if ($After) {$Query += " after:$($After.Trim())"}
-
- if ($HTML) {$Query += " html:$($HTML.Trim())"}
-
- if ($ISP) {$Query += " isp:`'$($ISP.Trim())`'"}
-
- if ($Link) {$Query += " link:$($Link.join(','))"}
-
- if ($Org) {$Query += " org:$($Org.Trim())"}
-
- if ($NTP_IP) {$Query += " ntp.ip:$($NTP_IP.Trim())"}
-
- if ($NTP_IP_Count) {$Query += " ntp.ip_count:$($NTP_IP_Count.Trim())"}
-
- if ($NTP_More) {$Query += ' ntp.more:True'}
-
- if ($NTP_Port) {$Query += " ntp.port:$($NTP_Port.Trim())"}
-
- if ($Title) {$Query += " title:$($Title.Trim())"}
-
- if ($Version) {$Query += " version:$($Version.Trim())"}
-
- if ($Product) {$Query += " product:$($Product.Trim())"}
-
- # Set propper request parameters.
- $Body = @{'key'= $APIKey; 'query'= $Query}
-
- if ($Page)
- {
- $Body.Add('page', $Page)
- }
-
- if ($Offset)
- {
- $Body.Add('offset',$Offset)
- }
-
- if ($Limit)
- {
- $Body.Add('limit',$Limit)
- }
-
- if ($Minify)
- {
- $Body.Add('minify','True')
- }
- else
- {
- $Body.Add('minify','False')
- }
-
- if ($Facets)
- {
- $Body.Add('facets',$Facets)
- }
-
- # Start building parameters for REST Method invokation.
- $Params = @{}
- $Params.add('Body', $Body)
- $Params.add('Method', 'Get')
- $Params.add('Uri',[uri]'https://api.shodan.io/shodan/host/search')
-
- # Check if connection will be made thru a proxy.
- if ($PsCmdlet.ParameterSetName -eq 'Proxy')
- {
- $Params.Add('Proxy', $Proxy)
-
- if ($ProxyCredential)
- {
- $Params.Add('ProxyCredential', $ProxyCredential)
- }
-
- if ($ProxyUseDefaultCredentials)
- {
- $Params.Add('ProxyUseDefaultCredentials', $ProxyUseDefaultCredentials)
- }
- }
-
- # Check if we will be doing certificate pinning by checking the certificate thumprint.
- if ($CertificateThumbprint)
- {
- $Params.Add('CertificateThumbprint', $CertificateThumbprint)
- }
- }
- Process
- {
-
- $ReturnedObject = Invoke-RestMethod @Params
- if ($ReturnedObject)
- {
- if ($ReturnedObject.total -ne 0)
- {
- $matches = @()
- foreach($match in $ReturnedObject.matches)
- {
- $match.pstypenames.insert(0,'Shodan.Host.Match')
- $matches = $matches + $match
- }
-
- $properties = [ordered]@{
- 'Total' = $ReturnedObject.total;
- 'Matches' = $matches;
- 'Facets' = $ReturnedObject.facets
- }
-
- $searchobj = [pscustomobject]$properties
- $searchobj.pstypenames.insert(0,'Shodan.Host.Search')
- $searchobj
- }
- else
- {
- Write-Warning -Message 'No matches found.'
- }
- }
- }
- End
- {
- }
-}
-
-# .ExternalHelp Posh-Shodan.Help.xml
-function Measure-ShodanHost
-{
- [CmdletBinding(DefaultParameterSetName = 'Direct')]
- Param
- (
- # Shodan developer API key
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Proxy')]
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Direct')]
- [string]
- $APIKey,
-
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Proxy')]
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Direct')]
- [string]
- $CertificateThumbprint,
-
- [Parameter(Mandatory=$true,
- ParameterSetName = 'Proxy')]
- [string]
- $Proxy,
-
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Proxy')]
- [Management.Automation.PSCredential]$ProxyCredential,
-
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Proxy')]
- [Switch]
- $ProxyUseDefaultCredentials,
-
- # Text to query for.
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Proxy')]
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Direct')]
- [string]
- $Query = '',
-
- # Find devices located in the given city. It's best combined with the
- # 'Country' filter to make sure you get the city in the country you
- # want (city names are not always unique).
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Proxy')]
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Direct')]
- [string]
- $City,
-
- # Narrow results down by country.
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Proxy')]
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Direct')]
- [string]
- $Country,
-
- # Latitude and longitude.
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Proxy')]
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Direct')]
- [string]
- $Geo,
-
- # Search for hosts that contain the value in their hostname.
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Proxy')]
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Direct')]
- [string]
- $Hostname,
-
- # Limit the search results to a specific IP or subnet. It uses CIDR
- # notation to designate the subnet range.
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Proxy')]
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Direct')]
- [string]
- $Net,
-
- # Specific operating systems. Common possible values are: windows,
- # linux and cisco.
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Proxy')]
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Direct')]
- [string]
- $OS,
-
- # Search the HTML of the website for the given value.
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Proxy')]
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Direct')]
- [string]
- $HTML,
-
- # Find devices based on the upstream owner of the IP netblock.
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Proxy')]
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Direct')]
- [string]
- $ISP,
-
- # The network link type. Possible values are: "Ethernet or modem",
- # "generic tunnel or VPN", "DSL", "IPIP or SIT", "SLIP", "IPSec or
- # "GRE", "VLAN", "jumbo Ethernet", "Google", "GIF", "PPTP", "loopback",
- # "AX.25 radio modem".
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Proxy')]
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Direct')]
- [ValidateSet('Ethernet or modem', 'generic tunnel or VPN', 'DSL',
- 'IPIP or SIT', 'SLIP', 'IPSec or GRE', 'VLAN',
- 'jumbo Ethernet','Google', 'GIF', 'PPTP', 'loopback',
- 'AX.25 radio modem')]
- [string[]]
- $Link,
-
- #Find NTP servers that had the given IP in their monlist.
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Proxy')]
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Direct')]
- [string]
- $NTP_IP,
-
- # Find NTP servers that return the given number of IPs in the initial monlist response.
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Proxy')]
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Direct')]
- [string]
- $NTP_IP_Count,
-
- # Find NTP servers that had IPs with the given port in their monlist.
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Proxy')]
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Direct')]
- [int]
- $NTP_Port,
-
- # Whether or not more IPs were available for the given NTP server.
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Proxy')]
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Direct')]
- [switch]
- $NTP_More,
-
- # Find devices based on the owner of the IP netblock.
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Proxy')]
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Direct')]
- [string]
- $Org,
-
- # Filter using the name of the software/ product; ex: product:Apache
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Proxy')]
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Direct')]
- [string]
- $Product,
-
- # Filter the results to include only products of the given version; ex: product:apache version:1.3.37
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Proxy')]
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Direct')]
- [string]
- $Version,
-
- # Search the title of the website.
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Proxy')]
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Direct')]
- [string]
- $Title,
-
- # Port number to narrow the search to specific services.
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Proxy')]
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Direct')]
- [string]
- $Port,
-
- # Limit search for data that was collected before the given date in
- # format day/month/year.
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Proxy')]
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Direct')]
- [string]
- $Before,
-
- # Limit search for data that was collected after the given date in
- # format day/month/year.
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Proxy')]
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Direct')]
- [string]
- $After,
-
- # The page number to page through results 100 at a time. Overrides the
- # "offset" and "limit" parameters if they were provided (default: 1)
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Proxy')]
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Direct')]
- [int]
- $Page,
-
- # The positon from which the search results should be returned (default: 0)
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Proxy')]
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Direct')]
- [int]
- $Offset,
-
- # The number of results to be returned default(100)
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Proxy')]
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Direct')]
- [int]
- $Limit,
-
- # True or False; whether or not to truncate some of the larger fields (default: True)
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Proxy')]
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Direct')]
- [bool]
- $Minify = $true,
-
- # A comma-separated list of properties to get summary information on. Property names
- # can also be in the format of "property:count", where "count" is the number of facets
- # that will be returned for a property (i.e. "country:100" to get the top 100 countries
- # for a search query).
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Proxy')]
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Direct')]
- [string]
- $Facets
-
- )
-
- Begin
- {
- if (!(Test-Path -Path variable:Global:ShodanAPIKey ) -and !($APIKey))
- {
- throw 'No Shodan API Key has been specified or set.'
- }
- elseif ((Test-Path -Path variable:Global:ShodanAPIKey ) -and !($APIKey))
- {
- $APIKey = $Global:ShodanAPIKey
- }
-
- # Create the query string to execute.
- if ($City) {$Query += " city:'$($City.Trim())'"}
-
- if ($Country) {$Query += " country_name:`'$($Country.Trim())`'"}
-
- if ($Geo) {$Query += " geo:$($Geo.Trim())"}
-
- if ($Hostname) {$Query += " hostname:$($Hostname.Trim())"}
-
- if ($Net) {$Query += " net:$($Net.Trim())"}
-
- if ($OS) {$Query += " os:$($OS.Trim())"}
-
- if ($Port) {$Query += " port:$($Port.Trim())"}
-
- if ($Before) {$Query += " before:$($Before.Trim())"}
-
- if ($After) {$Query += " after:$($After.Trim())"}
-
- if ($HTML) {$Query += " html:$($HTML.Trim())"}
-
- if ($ISP) {$Query += " isp:`'$($ISP.Trim())`'"}
-
- if ($Link) {$Query += " link:$($Link -join ',')"}
-
- if ($Org) {$Query += " org:$($Org.Trim())"}
-
- if ($NTP_IP) {$Query += " ntp.ip:$($NTP_IP.Trim())"}
-
- if ($NTP_IP_Count) {$Query += " ntp.ip_count:$($NTP_IP_Count.Trim())"}
-
- if ($NTP_More) {$Query += ' ntp.more:True'}
-
- if ($NTP_Port) {$Query += " ntp.port:$($NTP_Port.Trim())"}
-
- if ($Title) {$Query += " title:$($Title.Trim())"}
-
- if ($Version) {$Query += " version:$($Version.Trim())"}
-
- if ($Product) {$Query += " product:$($Product.Trim())"}
-
- # Set request parameters.
-
- $Body = @{'key'= $APIKey; 'query'= $Query}
-
- if ($Page) {$Body.Add('page', $Page)}
-
- if ($Offset) {$Body.Add('offset',$Offset)}
-
- if ($Limit) {$Body.Add('limit',$Limit)}
-
- if ($Minify)
- {
- $Body.Add('minify','True')
- }
- else
- {
- $Body.Add('minify','False')
- }
-
- if ($Facets) {$Body.Add('facets',$Facets)}
-
- # Start building parameters for REST Method invokation.
- $Params = @{}
- $Params.add('Body', $Body)
- $Params.add('Method', 'Get')
- $Params.add('Uri',[uri]'https://api.shodan.io/shodan/host/count')
-
- # Check if connection will be made thru a proxy.
- if ($PsCmdlet.ParameterSetName -eq 'Proxy')
- {
- $Params.Add('Proxy', $Proxy)
-
- if ($ProxyCredential)
- {
- $Params.Add('ProxyCredential', $ProxyCredential)
- }
-
- if ($ProxyUseDefaultCredentials)
- {
- $Params.Add('ProxyUseDefaultCredentials', $ProxyUseDefaultCredentials)
- }
- }
-
- # Check if we will be doing certificate pinning by checking the certificate thumprint.
- if ($CertificateThumbprint)
- {
- $Params.Add('CertificateThumbprint', $CertificateThumbprint)
- }
- }
- Process
- {
-
- $ReturnedObject = Invoke-RestMethod @Params
- if ($ReturnedObject)
- {
- $ReturnedObject.pstypenames.insert(0,'Shodan.Host.Count')
- $ReturnedObject
- }
- }
- End
- {
- }
-}
-
-# .ExternalHelp Posh-Shodan.Help.xml
-function Get-ShodanDNSResolve
-{
- [CmdletBinding(DefaultParameterSetName = 'Direct')]
- Param
- (
- # Shodan developer API key
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Proxy')]
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Direct')]
- [string]
- $APIKey,
-
- # Comma-separated list of hostnames ro resolve."
- [Parameter(Mandatory=$true,
- ParameterSetName = 'Proxy')]
- [Parameter(Mandatory=$true,
- ParameterSetName = 'Direct')]
- [string[]]
- $Hostname,
-
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Proxy')]
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Direct')]
- [string]
- $CertificateThumbprint,
-
- [Parameter(Mandatory=$true,
- ParameterSetName = 'Proxy')]
- [string]
- $Proxy,
-
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Proxy')]
- [Management.Automation.PSCredential]
- $ProxyCredential,
-
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Proxy')]
- [Switch]
- $ProxyUseDefaultCredentials
- )
-
- Begin
- {
- if (!(Test-Path -Path variable:Global:ShodanAPIKey ) -and !($APIKey))
- {
- throw 'No Shodan API Key has been specified or set.'
- }
- elseif ((Test-Path -Path variable:Global:ShodanAPIKey ) -and !($APIKey))
- {
- $APIKey = $Global:ShodanAPIKey
- }
-
- $Body = @{'key'= $APIKey; 'hostnames' = ($Hostname -join ',')}
-
- # Start building parameters for REST Method invokation.
- $Params = @{}
- $Params.add('Body', $Body)
- $Params.add('Method', 'Get')
- $Params.add('Uri',[uri]'https://api.shodan.io/dns/resolve')
-
- # Check if connection will be made thru a proxy.
- if ($PsCmdlet.ParameterSetName -eq 'Proxy')
- {
- $Params.Add('Proxy', $Proxy)
-
- if ($ProxyCredential)
- {
- $Params.Add('ProxyCredential', $ProxyCredential)
- }
-
- if ($ProxyUseDefaultCredentials)
- {
- $Params.Add('ProxyUseDefaultCredentials', $ProxyUseDefaultCredentials)
- }
- }
-
- # Check if we will be doing certificate pinning by checking the certificate thumprint.
- if ($CertificateThumbprint)
- {
- $Params.Add('CertificateThumbprint', $CertificateThumbprint)
- }
- }
- Process
- {
- $ReturnedObject = Invoke-RestMethod @Params
- if ($ReturnedObject)
- {
- $ReturnedObject.pstypenames.insert(0,'Shodan.DNS.Resolve')
- $ReturnedObject
- }
- }
- End
- {
- }
-}
-
-# .ExternalHelp Posh-Shodan.Help.xml
-function Get-ShodanDNSReverse
-{
- [CmdletBinding(DefaultParameterSetName = 'Direct')]
- Param
- (
- # Shodan developer API key
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Proxy')]
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Direct')]
- [string]
- $APIKey,
-
- # List of IP Addresses to resolve
- [Parameter(Mandatory=$true,
- ParameterSetName = 'Proxy')]
- [Parameter(Mandatory=$true,
- ParameterSetName = 'Direct')]
- [string[]]
- $IPAddress,
-
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Proxy')]
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Direct')]
- [string]
- $CertificateThumbprint,
-
- [Parameter(Mandatory=$true,
- ParameterSetName = 'Proxy')]
- [string]
- $Proxy,
-
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Proxy')]
- [Management.Automation.PSCredential]
- $ProxyCredential,
-
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Proxy')]
- [Switch]
- $ProxyUseDefaultCredentials
- )
-
- Begin
- {
- if (!(Test-Path -Path variable:Global:ShodanAPIKey ) -and !($APIKey))
- {
- throw 'No Shodan API Key has been specified or set.'
- }
- elseif ((Test-Path -Path variable:Global:ShodanAPIKey ) -and !($APIKey))
- {
- $APIKey = $Global:ShodanAPIKey
- }
-
- $Body = @{'key'= $APIKey; 'hostnames' = ($IPAddress -join ',')}
-
- # Start building parameters for REST Method invokation.
- $Params = @{}
- $Params.add('Body', $Body)
- $Params.add('Method', 'Get')
- $Params.add('Uri',[uri]'https://api.shodan.io/dns/resolve')
-
- # Check if connection will be made thru a proxy.
- if ($PsCmdlet.ParameterSetName -eq 'Proxy')
- {
- $Params.Add('Proxy', $Proxy)
-
- if ($ProxyCredential)
- {
- $Params.Add('ProxyCredential', $ProxyCredential)
- }
-
- if ($ProxyUseDefaultCredentials)
- {
- $Params.Add('ProxyUseDefaultCredentials', $ProxyUseDefaultCredentials)
- }
- }
-
- # Check if we will be doing certificate pinning by checking the certificate thumprint.
- if ($CertificateThumbprint)
- {
- $Params.Add('CertificateThumbprint', $CertificateThumbprint)
- }
- }
- Process
- {
- $ReturnedObject = Invoke-RestMethod @Params
- if ($ReturnedObject)
- {
- $ReturnedObject.pstypenames.insert(0,'Shodan.DNS.Resolve')
- $ReturnedObject
- }
- }
- End
- {
- }
-}
-
-# .ExternalHelp Posh-Shodan.Help.xml
-function Get-ShodanMyIP
-{
- [CmdletBinding(DefaultParameterSetName = 'Direct')]
- Param
- (
- # Shodan developer API key
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Proxy')]
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Direct')]
- [string]
- $APIKey,
-
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Proxy')]
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Direct')]
- [string]
- $CertificateThumbprint,
-
- [Parameter(Mandatory=$true,
- ParameterSetName = 'Proxy')]
- [string]
- $Proxy,
-
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Proxy')]
- [Management.Automation.PSCredential]
- $ProxyCredential,
-
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Proxy')]
- [Switch]
- $ProxyUseDefaultCredentials
- )
-
- Begin
- {
- if (!(Test-Path -Path variable:Global:ShodanAPIKey ) -and !($APIKey))
- {
- throw 'No Shodan API Key has been specified or set.'
- }
- elseif ((Test-Path -Path variable:Global:ShodanAPIKey ) -and !($APIKey))
- {
- $APIKey = $Global:ShodanAPIKey
- }
-
- # Start building parameters for REST Method invokation.
- $Params = @{}
- $Params.add('Body', @{'key'= $APIKey})
- $Params.add('Method', 'Get')
- $Params.add('Uri',[uri]'https://api.shodan.io/tools/myip')
-
- # Check if connection will be made thru a proxy.
- if ($PsCmdlet.ParameterSetName -eq 'Proxy')
- {
- $Params.Add('Proxy', $Proxy)
-
- if ($ProxyCredential)
- {
- $Params.Add('ProxyCredential', $ProxyCredential)
- }
-
- if ($ProxyUseDefaultCredentials)
- {
- $Params.Add('ProxyUseDefaultCredentials', $ProxyUseDefaultCredentials)
- }
- }
-
- # Check if we will be doing certificate pinning by checking the certificate thumprint.
- if ($CertificateThumbprint)
- {
- $Params.Add('CertificateThumbprint', $CertificateThumbprint)
- }
- }
- Process
- {
- $ReturnedObject = Invoke-RestMethod @Params
- if ($ReturnedObject)
- {
- $ReturnedObject
- }
- }
- End
- {
- }
-}
-
-# .ExternalHelp Posh-Shodan.Help.xml
-function Search-ShodanExploit
-{
- [CmdletBinding(DefaultParameterSetName = 'Direct')]
- Param
- (
- # Shodan developer API key
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Proxy')]
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Direct')]
- [string]
- $APIKey,
-
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Proxy')]
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Direct')]
- [string]
- $CertificateThumbprint,
-
- [Parameter(Mandatory=$true,
- ParameterSetName = 'Proxy')]
- [string]
- $Proxy,
-
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Proxy')]
- [Management.Automation.PSCredential]
- $ProxyCredential,
-
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Proxy')]
- [Switch]
- $ProxyUseDefaultCredentials,
-
- # list of properties to get summary information on.
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Proxy')]
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Direct')]
- [ValidateSet('author', 'platform', 'port', 'source', 'type')]
- [string[]]
- $Facets,
-
- # Text to query for.
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Proxy')]
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Direct')]
- [string]
- $Query,
-
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Proxy')]
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Direct')]
- [int]
- $Page,
-
- # CVE ID
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Proxy')]
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Direct')]
- [string]$CVE,
-
- # OpenSource Vulnerability Databse ID
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Proxy')]
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Direct')]
- [string]$OSVDB,
-
- # SecurityFocus BID Number
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Proxy')]
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Direct')]
- [string]$BID,
-
- # Microsoft Buletin (MS012-020)
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Proxy')]
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Direct')]
- [string]$MSB,
-
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Proxy')]
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Direct')]
- [ValidateSet('aix', 'asp', 'bsd', 'bsd/ppc', 'bsd/x86','bsdi/x86','cgi',
- 'freebsd','freebsd/x86','freebsd/x86-64','generator','hardware', 'hp-ux',
- 'irix', 'jsp', 'linux', 'linux/amd64', 'linux/mips', 'linux/ppc', 'linux/sparc',
- 'linux/x86', 'linux/x86-64', 'minix', 'multiple', 'netbsd/x86', 'novell', 'openbsd',
- 'openbsd/x86', 'os-x/ppc', 'osx', 'php','plan9', 'qnx', 'sco', 'sco/x86',
- 'solaris', 'solaris/sparc', 'solaris/x86', 'tru64', 'ultrix', 'unix', 'unixware',
- 'win32','win64','windows','arm','cfm')]
- [string]$Platform,
-
- # Param2 help description
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Proxy')]
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Direct')]
- [ValidateSet('Local', 'Papers', 'Remote', 'Shellcode', 'WebApps', 'DoS')]
- [string]$Type,
-
- # The port number for the affected service if the exploit is remote.
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Proxy')]
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Direct')]
- [int]$Port,
-
- # The author of the exploit/ vulnerability.
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Proxy')]
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Direct')]
- [string]$Author,
-
- # When the exploit was released format day/month/year..
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Proxy')]
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Direct')]
- [string]$Date,
-
- # The description of the exploit, how it works and where it applies.
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Proxy')]
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Direct')]
- [string]$Description,
-
- # The title or short description for the exploit if available.
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Proxy')]
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Direct')]
- [string]$Title
- )
-
- Begin
- {
- if (!(Test-Path -Path variable:Global:ShodanAPIKey ) -and !($APIKey))
- {
- throw 'No Shodan API Key has been specified or set.'
- }
- elseif ((Test-Path -Path variable:Global:ShodanAPIKey ) -and !($APIKey))
- {
- $APIKey = $Global:ShodanAPIKey
- }
-
- # Build the query string with filters selected
- if ($CVE)
- {
- $Query += " cve:$($CVE.Trim())"
- }
-
- if ($OSVDB)
- {
- $Query += " osvdb:$($OSVDB.Trim())"
- }
-
- if ($BID)
- {
- $Query += " bid:$($BID.Trim())"
- }
-
- if ($MSB)
- {
- $Query += " msb:$($MSB.Trim())"
- }
-
- if ($Platform)
- {
- $Query += " platform:$($Platform.Trim())"
- }
-
- if ($Type)
- {
- $Query += " type:$($Type.Trim())"
- }
-
- if ($Port)
- {
- $Query += " port:$($Port)"
- }
-
- if ($Author)
- {
- $Query += " author:$($Author.Trim())"
- }
-
- if ($Date)
- {
- $Query += " date:$($Date.Trim())"
- }
-
- if ($Description)
- {
- $Query += " description:$($Description.Trim())"
- }
-
- if ($Title)
- {
- $Query += " title:$($Title.Trim())"
- }
-
- # Set base request body.
- $Body = @{'key'= $APIKey; 'query' = $Query}
-
- if ($Facets)
- {
- $Body.Add('facets', ($Facets -join ','))
- }
-
- if ($Page)
- {
- $Body.Add('page', $Page)
- }
-
- # Start building parameters for REST Method invokation.
- $Params = @{}
- $Params.add('Body', $Body)
- $Params.add('Method', 'Get')
- $Params.add('Uri',[uri]'https://exploits.shodan.io/api/search')
-
- # Check if connection will be made thru a proxy.
- if ($PsCmdlet.ParameterSetName -eq 'Proxy')
- {
- $Params.Add('Proxy', $Proxy)
-
- if ($ProxyCredential)
- {
- $Params.Add('ProxyCredential', $ProxyCredential)
- }
-
- if ($ProxyUseDefaultCredentials)
- {
- $Params.Add('ProxyUseDefaultCredentials', $ProxyUseDefaultCredentials)
- }
- }
-
- # Check if we will be doing certificate pinning by checking the certificate thumprint.
- if ($CertificateThumbprint)
- {
- $Params.Add('CertificateThumbprint', $CertificateThumbprint)
- }
- }
- Process
- {
- $ReturnedObject = Invoke-RestMethod @Params
- if ($ReturnedObject)
- {
- $ReturnedObject.pstypenames.insert(0,'Shodan.Exploit.Search')
- $ReturnedObject
- }
- }
- End
- {
- }
-}
-
-# .ExternalHelp Posh-Shodan.Help.xml
-function Measure-ShodanExploit
-{
- [CmdletBinding(DefaultParameterSetName = 'Direct')]
- Param
- (
- # Shodan developer API key
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Proxy')]
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Direct')]
- [string]
- $APIKey,
-
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Proxy')]
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Direct')]
- [string]
- $CertificateThumbprint,
-
- [Parameter(Mandatory=$true,
- ParameterSetName = 'Proxy')]
- [string]
- $Proxy,
-
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Proxy')]
- [Management.Automation.PSCredential]
- $ProxyCredential,
-
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Proxy')]
- [Switch]
- $ProxyUseDefaultCredentials,
-
- # list of properties to get summary information on.
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Proxy')]
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Direct')]
- [ValidateSet('author', 'platform', 'port', 'source', 'type')]
- [string[]]
- $Facets,
-
- # Text to query for.
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Proxy')]
- [Parameter(Mandatory=$false,
- ParameterSetName = 'Direct')]
- [string]
- $Query
- )
-
- Begin
- {
- if (!(Test-Path -Path variable:Global:ShodanAPIKey ) -and !($APIKey))
- {
- throw 'No Shodan API Key has been specified or set.'
- }
- elseif ((Test-Path -Path variable:Global:ShodanAPIKey ) -and !($APIKey))
- {
- $APIKey = $Global:ShodanAPIKey
- }
-
- $Body = @{'key'= $APIKey; 'query' = $Query}
-
- if ($Facets)
- {
- $Body.Add('facets', ($Facets -join ','))
- }
-
- # Start building parameters for REST Method invokation.
- $Params = @{}
- $Params.add('Body', $Body)
- $Params.add('Method', 'Get')
- $Params.add('Uri',[uri]'https://exploits.shodan.io/api/count')
-
- # Check if connection will be made thru a proxy.
- if ($PsCmdlet.ParameterSetName -eq 'Proxy')
- {
- $Params.Add('Proxy', $Proxy)
-
- if ($ProxyCredential)
- {
- $Params.Add('ProxyCredential', $ProxyCredential)
- }
-
- if ($ProxyUseDefaultCredentials)
- {
- $Params.Add('ProxyUseDefaultCredentials', $ProxyUseDefaultCredentials)
- }
- }
-
- # Check if we will be doing certificate pinning by checking the certificate thumprint.
- if ($CertificateThumbprint)
- {
- $Params.Add('CertificateThumbprint', $CertificateThumbprint)
- }
- }
- Process
- {
- $ReturnedObject = Invoke-RestMethod @Params
- if ($ReturnedObject)
- {
- $ReturnedObject.pstypenames.insert(0,'Shodan.Exploit.Count')
- $ReturnedObject
- }
- }
- End
- {
- }
-}
\ No newline at end of file
diff --git a/Notebooks/PowerShell/Test/untitled.md b/Notebooks/PowerShell/Test/untitled.md
deleted file mode 100644
index 16d45a8..0000000
--- a/Notebooks/PowerShell/Test/untitled.md
+++ /dev/null
@@ -1,2 +0,0 @@
-Red Team Tools
-- https://github.com/samratashok/nishang
\ No newline at end of file
diff --git a/Notebooks/PowerShell/credentials.example b/Notebooks/PowerShell/credentials.example
deleted file mode 100644
index 959853e..0000000
--- a/Notebooks/PowerShell/credentials.example
+++ /dev/null
@@ -1,6 +0,0 @@
-{
- 'tenantDomain' : 'security.xyz',
- 'tenantId' : 'xxxxxxx-xxxxx-xxxxx-xxxx-xxxxxx',
- 'client_id' : 'xxxxxx-xxxxx-xxxx-xxxx-xxxxxxxx',
- 'client_secret' : 'xxxxxxxxxxxxxxx-xxxxxx-xxxxxxxx'
-}
\ No newline at end of file
diff --git a/Notebooks/Python/Microsoft/Security/Microsoft Graph/Security Alert Assignment and Tracking.ipynb b/Notebooks/Python/Microsoft/Security/Microsoft Graph/Security Alert Assignment and Tracking.ipynb
deleted file mode 100644
index 344034f..0000000
--- a/Notebooks/Python/Microsoft/Security/Microsoft Graph/Security Alert Assignment and Tracking.ipynb
+++ /dev/null
@@ -1,391 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "# Introduction\n",
- "This notebook shows how to use the [Microsoft Graph Security API](https://aka.ms/graphsecuritydocs). It defines a Python wrapper for calling the API to make it easy to access [Microsoft Graph Security alerts](https://aka.ms/graphsecurityalerts). While the APIs are documented and supported,\n",
- "the wrapper in this notebook is a sample and is not an official programming interface.\n",
- "\n",
- "Author: [Microsoft Graph Security Team](graphsecfeedback@microsoft.com) (Inspired by [@JohnLaTwC](https://twitter.com/JohnLaTwC))\n",
- "\n",
- "## Links to Microsoft Graph Security API documentation and other samples\n",
- "\n",
- "[Overview of Microsoft Graph Security](https://aka.ms/graphsecuritydocs)\n",
- "\n",
- "[What are alerts?](https://aka.ms/graphsecurityalerts)\n",
- "\n",
- "[Alert Schema - list of properties and descriptions](https://docs.microsoft.com/en-us/graph/api/resources/alert?view=graph-rest-1.0) \n",
- "\n",
- "[Authorization - Application-only and User-Delegated](https://docs.microsoft.com/graph/security-authorization?view=graph-rest-1.0)\n",
- "\n",
- "[More Samples](https://aka.ms/graphsecurityapicode)\n",
- "\n",
- "[OData query examples](https://docs.microsoft.com/graph/query-parameters)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "# Authentication - Initialize secrets\n",
- "\n",
- "Download this notebook and follow the steps below to get the application ID and secret that you can use to authenticate and get data from your Azure Active Directory (Azure AD) tenant using this notebook. \n",
- "1.\t[Register your application](https://docs.microsoft.com/en-us/graph/auth-v2-service#1-register-your-app) for this notebook in Azure AD in application only mode. \n",
- "2.\t[Configure permissions](https://docs.microsoft.com/en-us/graph/auth-v2-service#2-configure-permissions-for-microsoft-graph) and be sure to add the `SecurityEvents.ReadWrite.All` permission to your application.\n",
- "3. Get your Azure AD tenant administrator to [grant tenant administration consent](https://docs.microsoft.com/en-us/graph/auth-v2-service#3-get-administrator-consent) to your application. This is a one-time activity unless permissions change for the application. \n",
- "\n",
- "When your app is registered to call the Microsoft Graph Security API you need to pass the application ID and application secret from the above mentioned steps in to this sample. \n",
- "\n",
- "Use either plain text input to enter your secret in the `get_secret` function or get it from your environment variable in the `get_secret` function below the first one. Use only one of these functions to get secret. "
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "def get_secret(secret_name):\n",
- " return {'GRAPHSEC_DEMO_appId':'<>',\n",
- " 'GRAPHSEC_DEMO_appSecret':'<>',\n",
- " 'GRAPHSEC_DEMO_tenantId':'<>'}[secret_name]"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "## e.g. custom way to access secrets\n",
- "def get_secret(secret_name):\n",
- " import os\n",
- " return os.environ.get(secret_name)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "appId = get_secret('GRAPHSEC_DEMO_appId')\n",
- "appSecret = get_secret('GRAPHSEC_DEMO_appSecret') \n",
- "tenantId = get_secret('GRAPHSEC_DEMO_tenantId')\n",
- "print(\"If your secrets were initialized properly you should see your tenant id.\\nTenant Id: %s \" % tenantId)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "# Getting Started\n",
- "All the API Wrapper code is below. Activate it by clicking in the cell and hitting Shift+Enter"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# -------------------------------------------------------------------------\n",
- "# Copyright (c) Microsoft Corporation. All rights reserved.\n",
- "# Licensed under the MIT License. \n",
- "# --------------------------------------------------------------------------\n",
- "\n",
- "## https://aka.ms/graphsecuritydocs\n",
- "\n",
- "import json\n",
- "import urllib.request\n",
- "import urllib.parse\n",
- "import pandas as pd\n",
- "import re\n",
- "\n",
- " \n",
- "class MicrosoftGraphSecurityAPI:\n",
- " def __init__(self, tenantId, appId, appSecret, fUsePandas=True, \n",
- " api_root=\"https://graph.microsoft.com/\", api_version=\"v1.0\"):\n",
- " url = \"https://login.microsoftonline.com/%s/oauth2/v2.0/token\" % (tenantId)\n",
- "\n",
- " self.fDebug = False\n",
- "\n",
- " body = {\n",
- " 'client_id' : appId,\n",
- " 'client_secret' : appSecret,\n",
- " 'grant_type' : 'client_credentials',\n",
- " 'scope': 'https://graph.microsoft.com/.default'\n",
- " }\n",
- "\n",
- " ## authenticate and obtain AAD Token for future calls\n",
- " data = urllib.parse.urlencode(body).encode(\"utf-8\")\n",
- " req = urllib.request.Request(url, data)\n",
- " response = urllib.request.urlopen(req)\n",
- " jsonResponse = json.loads(response.read().decode())\n",
- " self.aadToken = jsonResponse[\"access_token\"]\n",
- " self.headers = { \n",
- " 'Content-Type' : 'application/json',\n",
- " 'Accept' : 'application/json',\n",
- " 'Authorization' : \"Bearer \" + self.aadToken\n",
- " }\n",
- " self.fUsePandas = fUsePandas # use pandas DataFrame for collections of objects, else return a list\n",
- " self.api_root = api_root + api_version \n",
- " if len(self.aadToken) > 0:\n",
- " print(\"Connected.\")\n",
- " \n",
- " def set_output_type(self, fUsePandas=True):\n",
- " self.fUsePandas = fUsePandas \n",
- "\n",
- " def set_debug_output(self, fDebug=True):\n",
- " self.fDebug = fDebug \n",
- " \n",
- " def __validate_arguments(self,args, valid_params):\n",
- " if len(args) == 0:\n",
- " raise ValueError ('argument must be one of %s' % str(list(valid_params.keys())))\n",
- " elif len(args) > 1:\n",
- " raise ValueError ('only one id can be used at a time')\n",
- " else:\n",
- " selector = next(iter(args))\n",
- " selector_value= next(iter(args.values()))\n",
- " if selector not in list(valid_params.keys()):\n",
- " raise ValueError ('argument must be one of %s' % str(list(valid_params.keys())))\n",
- " return (selector, selector_value)\n",
- "\n",
- " def __make_request(self,url, params=None):\n",
- " \n",
- " if self.fDebug:\n",
- " print(url)\n",
- " req = urllib.request.Request(url, headers=self.headers)\n",
- " try:\n",
- " response = urllib.request.urlopen(req)\n",
- " except urllib.error.HTTPError as e:\n",
- " raise e\n",
- " \n",
- " jsonResponse = json.loads(response.read().decode())\n",
- " if type(jsonResponse) == int:\n",
- " if self.fUsePandas:\n",
- " return pd.DataFrame([jsonResponse])\n",
- " else:\n",
- " return jsonResponse\n",
- " if 'value' in jsonResponse:\n",
- " res = jsonResponse[\"value\"]\n",
- " if len(res) == 0:\n",
- " res = {}\n",
- " else:\n",
- " res = jsonResponse \n",
- " if self.fUsePandas:\n",
- " return pd.io.json.json_normalize(res)\n",
- " return res\n",
- "\n",
- " def __prepare_param_dict_from_filter_str(self, filterstr):\n",
- " get_params = {}\n",
- " for filter_param in re.split(\"[\\?\\&]+\", filterstr):\n",
- " if len(filter_param)> 0:\n",
- " attr = filter_param.split('=')[0]\n",
- " val = filter_param.split('=')[1]\n",
- " get_params[attr]= val\n",
- " return get_params\n",
- " \n",
- " def __get_json_alert(self, alertid=None):\n",
- " _pandas = self.fUsePandas\n",
- " self.fUsePandas = False\n",
- " alert_as_json = self.alerts(alertid=alertid)\n",
- " self.fUsePandas = _pandas\n",
- " return alert_as_json\n",
- " \n",
- " def alerts(self, **kwargs):\n",
- " alert_url = self.api_root + \"/security/alerts\"\n",
- " get_params = None\n",
- " \n",
- " valid_params = {\n",
- " 'filterstr' : alert_url + '?%s',\n",
- " 'alertid' : alert_url + '/%s',\n",
- " 'userid' : alert_url + \"?$filter=userStates/any(d:d/userPrincipalName eq '%s')\",\n",
- " 'ip' : alert_url + \"?$filter=hostStates/any(d:d/privateIpAddress eq '%s')\",\n",
- " 'hostfqdn' : alert_url + \"?$filter=hostStates/any(d:d/fqdn eq '%s')\", \n",
- " 'filehash' : alert_url + \"?$filter=fileStates/any(d:d/fileHash/hashValue eq '%s')\",\n",
- " 'filename' : alert_url + \"?$filter=fileStates/any(d:d/name eq '%s')\", \n",
- " 'domain' : alert_url + \"?$filter=networkConnections/any(d:d/destinationDomain eq '%s')\" \n",
- " }\n",
- " (selector, selector_value) = self.__validate_arguments(kwargs, valid_params)\n",
- " \n",
- " if selector == 'filterstr':\n",
- " get_params = self.__prepare_param_dict_from_filter_str(selector_value)\n",
- " if get_params is not None:\n",
- " url = valid_params[selector] % urllib.parse.urlencode(get_params)\n",
- " else:\n",
- " url = valid_params[selector] % selector_value\n",
- " url = urllib.parse.quote( url , safe=\"%/:=&?~#+!$,;'@()*[]\") # Url encode spaces \n",
- "\n",
- " return self.__make_request(url)\n",
- " \n",
- " def update_alert(self, alertid=None, alertbody=None):\n",
- " import requests \n",
- "\n",
- " alert_url = self.api_root + \"/security/alerts\"\n",
- " \n",
- " valid_params = {\n",
- " 'alertid' : alert_url + '/%s'\n",
- " }\n",
- " (selector, selector_value) = self.__validate_arguments({\"alertid\": alertid}, valid_params)\n",
- " \n",
- " if alertbody == None:\n",
- " raise ValueError ('Request body cannot be empty')\n",
- " \n",
- " headers = self.headers\n",
- " headers['Prefer'] = \"return=representation\"\n",
- " \n",
- " _old_alert = self.__get_json_alert(alertid=alertid) \n",
- " \n",
- " alertbody[\"vendorInformation\"] = _old_alert[\"vendorInformation\"] # vendorInformation is required to PATCH an alert\n",
- " \n",
- " url = valid_params[selector] % selector_value\n",
- " json_body = json.dumps(alertbody)\n",
- " response = requests.patch(url, json_body, headers=headers)\n",
- "\n",
- " jsonResponse = response.json()\n",
- "\n",
- " if self.fUsePandas:\n",
- " return pd.io.json.json_normalize(jsonResponse)\n",
- " return jsonResponse\n",
- "\n",
- " \n",
- "print(\"Sample Microsoft Graph Security API code loaded\")"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "# hit Shift-Enter in this cell\n",
- "\n",
- "# NOTE: endpoint authorization will periodically time out and you will need to re-run this command to re-authenticate\n",
- "# if you're able to call the API (client app registered properly), and you get an exception \n",
- "# with a HTTP error 401 Unauthorized, re-run this command to re-initiate the endpoint\n",
- "\n",
- "MsftGraphSec_api = MicrosoftGraphSecurityAPI(tenantId, appId, appSecret)\n",
- "MsftGraphSec_api.set_debug_output()"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "# Testing Get Alerts\n",
- "\n",
- "Let's query the most recent alerts using the OData TOP keyword. The `$top=1` query will return 1 of the most recent alerts from *each* [Microsoft Graph Security alert provider](https://aka.ms/graphsecurityalerts). "
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "MsftGraphSec_api.alerts(filterstr = \"$top=1\")[[\"id\", \"assignedTo\", \"title\", \"description\", \"comments\", \"severity\", \"vendorInformation.provider\", \"vendorInformation.vendor\" ]]"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Update alerts\n",
- "We can assigned someone to one of the alerts from the previous query by updating the `assignedTo` property of the alert. **Note:** vendorInformation is required. \n",
- "https://docs.microsoft.com/graph/api/alert-update"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "new_assigned_to = \"<< email you like to assign >>\"\n",
- "\n",
- "new_data = {\"assignedTo\": new_assigned_to}\n",
- "\n",
- "MsftGraphSec_api.update_alert('<< Id of the alert to update >>', new_data)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Get alerts by assignedTo\n",
- "\n",
- "You can [query alerts](https://docs.microsoft.com/en-us/graph/api/alert-list?view=graph-rest-1.0) with OData queries. OData provides a simple standardized syntax for selecting properties and filtering data\n",
- "\n",
- "A summary of the OData filters can be found [here](https://docs.microsoft.com/graph/query-parameters) "
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "MsftGraphSec_api.alerts(filterstr = \"$filter=assignedTo eq '{0}'\".format(new_assigned_to))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "# Query alerts by status\n",
- "## Get active alerts\n",
- "This query filters all alerts where the status is not equal(ne) to resolved. "
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "MsftGraphSec_api.alerts(filterstr = \"$filter=status ne 'resolved'\")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Get resolved alerts\n",
- "This query filters all alerts where the status is equal(eq) to resolved. "
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "MsftGraphSec_api.alerts(filterstr = \"$filter=status eq 'resolved'\")\n"
- ]
- }
- ],
- "metadata": {
- "kernelspec": {
- "display_name": "Python 3",
- "language": "python",
- "name": "python3"
- },
- "language_info": {
- "codemirror_mode": {
- "name": "ipython",
- "version": 3
- },
- "file_extension": ".py",
- "mimetype": "text/x-python",
- "name": "python",
- "nbconvert_exporter": "python",
- "pygments_lexer": "ipython3",
- "version": "3.8.6"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 4
-}
diff --git a/Notebooks/Python/Microsoft/Security/Microsoft Graph/Security Investigation Scenarios.ipynb b/Notebooks/Python/Microsoft/Security/Microsoft Graph/Security Investigation Scenarios.ipynb
deleted file mode 100644
index e393e9e..0000000
--- a/Notebooks/Python/Microsoft/Security/Microsoft Graph/Security Investigation Scenarios.ipynb
+++ /dev/null
@@ -1,159 +0,0 @@
-{
- "cells": [
- {
- "metadata": {},
- "cell_type": "markdown",
- "source": "# Introduction\nThis notebook shows how to use the [Microsoft Graph Security API](https://aka.ms/graphsecuritydocs). It defines a Python wrapper for calling the API to make it easy to access [Microsoft Graph Security alerts](https://aka.ms/graphsecurityalerts). While the APIs are documented and supported,\nthe wrapper in this notebook is a sample and is not an official programming interface.\n\nAuthor: [Microsoft Graph Security Team](graphsecfeedback@microsoft.com) (Inspired by [@JohnLaTwC](https://twitter.com/JohnLaTwC))\n\n## Links to Microsoft Graph Security API documentation and other samples\n\n[Overview of Microsoft Graph Security](https://aka.ms/graphsecuritydocs)\n\n[What are alerts?](https://aka.ms/graphsecurityalerts)\n\n[Alert Schema - list of properties and descriptions](https://docs.microsoft.com/en-us/graph/api/resources/alert?view=graph-rest-1.0) \n\n[Authorization - Application-only and User-Delegated](https://docs.microsoft.com/graph/security-authorization?view=graph-rest-1.0)\n\n[More Samples](https://aka.ms/graphsecurityapicode)\n\n[OData query examples](https://docs.microsoft.com/graph/query-parameters)"
- },
- {
- "metadata": {},
- "cell_type": "markdown",
- "source": "# Authentication - Initialize secrets\n\nDownload this notebook and follow the steps below to get the application ID and secret that you can use to authenticate and get data from your Azure Active Directory (Azure AD) tenant using this notebook. \n1.\t[Register your application](https://docs.microsoft.com/en-us/graph/auth-v2-service#1-register-your-app) for this notebook in Azure AD in application only mode. \n2.\t[Configure permissions](https://docs.microsoft.com/en-us/graph/auth-v2-service#2-configure-permissions-for-microsoft-graph) and be sure to add the `SecurityEvents.ReadWrite.All` permission to your application.\n3. Get your Azure AD tenant administrator to [grant tenant administration consent](https://docs.microsoft.com/en-us/graph/auth-v2-service#3-get-administrator-consent) to your application. This is a one-time activity unless permissions change for the application. \n\nWhen your app is registered to call the Microsoft Graph Security API you need to pass the application ID and application secret from the above mentioned steps in to this sample. \n\nUse either plain text input to enter your secret in the `get_secret` function or get it from your environment variable in the `get_secret` function below the first one. Use only one of these functions to get secret. "
- },
- {
- "metadata": {
- "trusted": true
- },
- "cell_type": "code",
- "source": "def get_secret(secret_name):\n return {'GRAPHSEC_DEMO_appId':'<>',\n 'GRAPHSEC_DEMO_appSecret':'<>',\n 'GRAPHSEC_DEMO_tenantId':'<>'}[secret_name]",
- "execution_count": null,
- "outputs": []
- },
- {
- "metadata": {
- "trusted": true
- },
- "cell_type": "code",
- "source": "## e.g. custom way to access secrets\ndef get_secret(secret_name):\n import os\n return os.environ.get(secret_name)",
- "execution_count": null,
- "outputs": []
- },
- {
- "metadata": {
- "trusted": true
- },
- "cell_type": "code",
- "source": "appId = get_secret('GRAPHSEC_DEMO_appId')\nappSecret = get_secret('GRAPHSEC_DEMO_appSecret') \ntenantId = get_secret('GRAPHSEC_DEMO_tenantId')\nprint(\"If your secrets were initialized properly you should see your tenant id.\\nTenant Id: %s \" % tenantId)",
- "execution_count": null,
- "outputs": []
- },
- {
- "metadata": {},
- "cell_type": "markdown",
- "source": "# Getting Started\nAll the API Wrapper code is below. Activate it by clicking in the cell and hitting Shift+Enter"
- },
- {
- "metadata": {
- "trusted": true
- },
- "cell_type": "code",
- "source": "# -------------------------------------------------------------------------\n# Copyright (c) Microsoft Corporation. All rights reserved.\n# Licensed under the MIT License. \n# --------------------------------------------------------------------------\n\n## https://aka.ms/graphsecuritydocs\n\nimport json\nimport urllib.request\nimport urllib.parse\nimport pandas as pd\nimport re\n \nclass MicrosoftGraphSecurityAPI:\n def __init__(self, tenantId, appId, appSecret, fUsePandas=True, \n api_root=\"https://graph.microsoft.com/\", api_version=\"v1.0\"):\n url = \"https://login.microsoftonline.com/%s/oauth2/v2.0/token\" % (tenantId)\n\n self.fDebug = False\n\n body = {\n 'client_id' : appId,\n 'client_secret' : appSecret,\n 'grant_type' : 'client_credentials',\n 'scope': 'https://graph.microsoft.com/.default'\n }\n\n ## authenticate and obtain AAD Token for future calls\n data = urllib.parse.urlencode(body).encode(\"utf-8\")\n req = urllib.request.Request(url, data)\n response = urllib.request.urlopen(req)\n jsonResponse = json.loads(response.read().decode())\n self.aadToken = jsonResponse[\"access_token\"]\n self.headers = { \n 'Content-Type' : 'application/json',\n 'Accept' : 'application/json',\n 'Authorization' : \"Bearer \" + self.aadToken\n }\n self.fUsePandas = fUsePandas # use pandas DataFrame for collections of objects, else return a list\n self.api_root = api_root + api_version \n if len(self.aadToken) > 0:\n print(\"Connected.\")\n \n def set_output_type(self, fUsePandas=True):\n self.fUsePandas = fUsePandas \n\n def set_debug_output(self, fDebug=True):\n self.fDebug = fDebug \n \n def __validate_arguments(self,args, valid_params):\n if len(args) == 0:\n raise ValueError ('argument must be one of %s' % str(list(valid_params.keys())))\n elif len(args) > 1:\n raise ValueError ('only one id can be used at a time')\n else:\n selector = next(iter(args))\n selector_value= next(iter(args.values()))\n if selector not in list(valid_params.keys()):\n raise ValueError ('argument must be one of %s' % str(list(valid_params.keys())))\n return (selector, selector_value)\n\n def __make_request(self,url, params=None):\n \n if self.fDebug:\n print(url)\n req = urllib.request.Request(url, headers=self.headers)\n try:\n response = urllib.request.urlopen(req)\n except urllib.error.HTTPError as e:\n raise e\n \n jsonResponse = json.loads(response.read().decode())\n if type(jsonResponse) == int:\n if self.fUsePandas:\n return pd.DataFrame([jsonResponse])\n else:\n return jsonResponse\n if 'value' in jsonResponse:\n res = jsonResponse[\"value\"]\n if len(res) == 0:\n res = {}\n else:\n res = jsonResponse \n if self.fUsePandas:\n return pd.io.json.json_normalize(res)\n return res\n\n def __prepare_param_dict_from_filter_str(self, filterstr):\n get_params = {}\n for filter_param in re.split(\"[\\?\\&]+\", filterstr):\n if len(filter_param)> 0:\n attr = filter_param.split('=')[0]\n val = filter_param.split('=')[1]\n get_params[attr]= val\n return get_params\n \n def alerts(self, **kwargs):\n alert_url = self.api_root + \"/security/alerts\"\n get_params = None\n \n valid_params = {\n 'filterstr' : alert_url + '?%s',\n 'alertid' : alert_url + '/%s',\n 'userid' : alert_url + \"?$filter=userStates/any(d:d/userPrincipalName eq '%s')\",\n 'ip' : alert_url + \"?$filter=hostStates/any(d:d/privateIpAddress eq '%s')\",\n 'hostfqdn' : alert_url + \"?$filter=hostStates/any(d:d/fqdn eq '%s')\", \n 'filehash' : alert_url + \"?$filter=fileStates/any(d:d/fileHash/hashValue eq '%s')\",\n 'filename' : alert_url + \"?$filter=fileStates/any(d:d/name eq '%s')\", \n 'domain' : alert_url + \"?$filter=networkConnections/any(d:d/destinationDomain eq '%s')\" \n }\n (selector, selector_value) = self.__validate_arguments(kwargs, valid_params)\n \n if selector == 'filterstr':\n get_params = self.__prepare_param_dict_from_filter_str(selector_value)\n if get_params is not None:\n url = valid_params[selector] % urllib.parse.urlencode(get_params)\n else:\n url = valid_params[selector] % selector_value\n url = urllib.parse.quote( url , safe=\"%/:=&?~#+!$,;'@()*[]\") # Url encode spaces \n\n return self.__make_request(url)\n \nprint(\"Sample Microsoft Graph Security API code loaded\")",
- "execution_count": null,
- "outputs": []
- },
- {
- "metadata": {
- "trusted": true
- },
- "cell_type": "code",
- "source": "# hit Shift-Enter in this cell\n\n# NOTE: endpoint authorization will periodically time out and you will need to re-run this command to re-authenticate\n# if you're able to call the API (client app registered properly), and you get an exception \n# with a HTTP error 401 Unauthorized, re-run this command to re-initiate the endpoint\n\nMsftGraphSec_api = MicrosoftGraphSecurityAPI(tenantId, appId, appSecret)\nMsftGraphSec_api.set_debug_output()",
- "execution_count": null,
- "outputs": []
- },
- {
- "metadata": {},
- "cell_type": "markdown",
- "source": "# Testing Get Alerts\n\nLet's query the most recent 5 alerts using the OData TOP keyword. The `$top=5` query will return 5 of the most recent alerts from *each* [Microsoft Graph Security alert provider](https://aka.ms/graphsecurityalerts). "
- },
- {
- "metadata": {
- "trusted": true
- },
- "cell_type": "code",
- "source": "MsftGraphSec_api.alerts(filterstr = \"$top=5\")",
- "execution_count": null,
- "outputs": []
- },
- {
- "metadata": {},
- "cell_type": "markdown",
- "source": "# Security Investigation Scenarios\nYou can [query alerts](https://docs.microsoft.com/en-us/graph/api/alert-list?view=graph-rest-1.0) with OData queries. OData provides a simple standardized syntax for selecting properties and filtering data\n\nA summary of the OData filters can be found [here](https://docs.microsoft.com/graph/query-parameters) \n\n## Querying alerts by UPN (User Principal Name)"
- },
- {
- "metadata": {
- "trusted": true
- },
- "cell_type": "code",
- "source": "MsftGraphSec_api.alerts( userid = '<>')",
- "execution_count": null,
- "outputs": []
- },
- {
- "metadata": {},
- "cell_type": "markdown",
- "source": "## Querying alerts by machine FQDNs (Fully Qualified Domain Name)\nYou can query alerts by machine fqdn, user id, ip, alert id, file sha1, domain, OData query, and more"
- },
- {
- "metadata": {
- "trusted": true
- },
- "cell_type": "code",
- "source": "MsftGraphSec_api.alerts( hostfqdn = '<>')",
- "execution_count": null,
- "outputs": []
- },
- {
- "metadata": {
- "trusted": true
- },
- "cell_type": "code",
- "source": "# query machines associated with an alert\nMsftGraphSec_api.alerts( alertid = '<>')[['id', 'hostStates']] #[['id', 'osBuild','osPlatform']]",
- "execution_count": null,
- "outputs": []
- },
- {
- "metadata": {
- "trusted": true
- },
- "cell_type": "code",
- "source": "# query alerts by machine name\nMsftGraphSec_api.alerts( filterstr = \"$filter=hostStates/any(d:d/netBiosName eq '<>')\")",
- "execution_count": null,
- "outputs": []
- },
- {
- "metadata": {},
- "cell_type": "markdown",
- "source": "## Querying alerts by private IP\nYou can query alerts by private IPs populated by the providers within the alert hostStates."
- },
- {
- "metadata": {
- "trusted": true
- },
- "cell_type": "code",
- "source": "MsftGraphSec_api.alerts( ip = '<>' )",
- "execution_count": null,
- "outputs": []
- }
- ],
- "metadata": {
- "kernelspec": {
- "name": "python36",
- "display_name": "Python 3.6",
- "language": "python"
- },
- "language_info": {
- "mimetype": "text/x-python",
- "nbconvert_exporter": "python",
- "name": "python",
- "pygments_lexer": "ipython3",
- "version": "3.6.6",
- "file_extension": ".py",
- "codemirror_mode": {
- "version": 3,
- "name": "ipython"
- }
- }
- },
- "nbformat": 4,
- "nbformat_minor": 2
-}
\ No newline at end of file
diff --git a/Notebooks/Python/Microsoft/Security/Microsoft Graph/Security Management and Investigation Sample.ipynb b/Notebooks/Python/Microsoft/Security/Microsoft Graph/Security Management and Investigation Sample.ipynb
deleted file mode 100644
index aa93d14..0000000
--- a/Notebooks/Python/Microsoft/Security/Microsoft Graph/Security Management and Investigation Sample.ipynb
+++ /dev/null
@@ -1,253 +0,0 @@
-{
- "cells": [
- {
- "metadata": {},
- "cell_type": "markdown",
- "source": "# Introduction\nThis notebook shows how to use the [Microsoft Graph Security API](https://aka.ms/graphsecuritydocs). It defines a Python wrapper for calling the API \nand several Jupyter magics to make it easy to access [Microsoft Graph Security alerts](https://aka.ms/graphsecurityalerts). While the APIs are documented and supported,\nthe wrapper in this notebook is a sample and is not an official programming interface.\n\nAuthor: [Microsoft Graph Security Team](graphsecfeedback@microsoft.com) (Inspired by [@JohnLaTwC](https://twitter.com/JohnLaTwC))\n\n## Links to Microsoft Graph Security API documentation and other samples\n\n[Overview of Microsoft Graph Security](https://aka.ms/graphsecuritydocs)\n\n[What are alerts?](https://aka.ms/graphsecurityalerts)\n\n[Alert Schema - list of properties and descriptions](https://docs.microsoft.com/en-us/graph/api/resources/alert?view=graph-rest-1.0) \n\n[Authorization - Application-only and User-Delegated](https://docs.microsoft.com/graph/security-authorization?view=graph-rest-1.0)\n\n[More Samples](https://aka.ms/graphsecurityapicode)\n\n[OData query examples](https://docs.microsoft.com/graph/query-parameters)"
- },
- {
- "metadata": {},
- "cell_type": "markdown",
- "source": "# Authentication - Initialize secrets\n\nDownload this notebook and follow the steps below to get the application ID and secret that you can use to authenticate and get data from your Azure Active Directory (Azure AD) tenant using this notebook. \n1.\t[Register your application](https://docs.microsoft.com/en-us/graph/auth-v2-service#1-register-your-app) for this notebook in Azure AD in application only mode. \n2.\t[Configure permissions](https://docs.microsoft.com/en-us/graph/auth-v2-service#2-configure-permissions-for-microsoft-graph) and be sure to add the `SecurityEvents.ReadWrite.All` permission to your application.\n3. Get your Azure AD tenant administrator to [grant tenant administration consent](https://docs.microsoft.com/en-us/graph/auth-v2-service#3-get-administrator-consent) to your application. This is a one-time activity unless permissions change for the application. \n\nWhen your app is registered to call the Microsoft Graph Security API you need to pass the application ID and application secret from the above mentioned steps in to this sample. \n\nUse either plain text input to enter your secret in the `get_secret` function or get it from your envionment variable in the `get_secret` function below the first one. Use only one of these functions to get secret. "
- },
- {
- "metadata": {
- "trusted": true
- },
- "cell_type": "code",
- "source": "def get_secret(secret_name):\n return {'GRAPHSEC_DEMO_appId':'<>',\n 'GRAPHSEC_DEMO_appSecret':'<>',\n 'GRAPHSEC_DEMO_tenantId':'<>',\n 'VT_API_KEY':'<>'}[secret_name]",
- "execution_count": null,
- "outputs": []
- },
- {
- "metadata": {
- "trusted": true
- },
- "cell_type": "code",
- "source": "## e.g. custom way to access secrets\ndef get_secret(secret_name):\n import os\n return os.environ.get(secret_name)",
- "execution_count": null,
- "outputs": []
- },
- {
- "metadata": {
- "trusted": true
- },
- "cell_type": "code",
- "source": "appId = get_secret('GRAPHSEC_DEMO_appId')\nappSecret = get_secret('GRAPHSEC_DEMO_appSecret') \ntenantId = get_secret('GRAPHSEC_DEMO_tenantId')\nvt_api_key = get_secret('VT_API_KEY')\nprint(\"If your secrets were initialized properly you should see your tenant id.\\nTenant Id: %s \" % tenantId)",
- "execution_count": null,
- "outputs": []
- },
- {
- "metadata": {},
- "cell_type": "markdown",
- "source": "# Getting Started\nAll the API Wrapper code is below. Activate it by clicking in the cell and hitting Shift+Enter"
- },
- {
- "metadata": {
- "trusted": true
- },
- "cell_type": "code",
- "source": "# -------------------------------------------------------------------------\n# Copyright (c) Microsoft Corporation. All rights reserved.\n# Licensed under the MIT License. \n# --------------------------------------------------------------------------\n\n## https://aka.ms/graphsecuritydocs\n\nimport json\nimport urllib.request\nimport urllib.parse\nimport pandas as pd\nimport re\nfrom IPython.core.magic import (register_line_magic, register_cell_magic,\n register_line_cell_magic)\n\nSPLIT_DELIMS = '[\\[\\] ;\\n\\t|,xX\"\\']'\n@register_line_cell_magic\ndef hash(line, cell=None):\n if cell is None:\n return line\n else: \n results = []\n for f in re.split(SPLIT_DELIMS,cell):\n p = re.compile('^[a-f0-9]{32}$'\n '|^[a-f0-9]{40}$'\n '|^[a-f0-9]{64}$'\n ,re.IGNORECASE)\n if p.search(f) is not None:\n if not f in results:\n results.append(f)\n \n return results \n\n# We delete these to avoid name conflicts for automagic to work\ndel hash \n\n@register_line_cell_magic\ndef vthash(line, cell=None):\n if cell is None:\n return MsftGraphSec_api.vtresults([line])\n else: \n results = []\n for f in re.split(SPLIT_DELIMS,cell):\n p = re.compile('^[a-f0-9]{32}$'\n '|^[a-f0-9]{40}$'\n '|^[a-f0-9]{64}$'\n ,re.IGNORECASE)\n if p.search(f) is not None:\n if not f in results:\n results.append(f)\n \n if len(results) == 0:\n return\n return MsftGraphSec_api.vtresults(results)\n \n\n# We delete these to avoid name conflicts for automagic to work\ndel vthash \n\n@register_line_cell_magic\ndef graph_sec_file(line, cell=None):\n if cell is None:\n return MsftGraphSec_api.alerts(filehash=line)\n else: \n results = []\n for f in re.split(SPLIT_DELIMS,cell):\n p = re.compile('^[a-f0-9]{32}$'\n '|^[a-f0-9]{40}$'\n '|^[a-f0-9]{64}$'\n ,re.IGNORECASE)\n if p.search(f) is not None:\n if not f in results:\n results.append(f)\n \n if len(results) == 0:\n return\n dfs = []\n for filehash in results:\n dfs.append(MsftGraphSec_api.alerts(filehash=filehash))\n import pandas as pd\n return pd.concat(dfs)\n \n# Delete these to avoid name conflicts for automagic to work\ndel graph_sec_file\n\n@register_line_cell_magic\ndef graph_sec_machine(line, cell=None):\n if cell is None:\n if re.match('^[a-f0-9]{40}$', line):\n return MsftGraphSec_api.machines(machineid=line)\n else:\n return MsftGraphSec_api.machines(filterstr=\"$filter=ComputerDnsName eq '%s'\" % line)\n else: \n results = []\n for f in re.split(SPLIT_DELIMS,cell):\n p = re.compile('^[a-f0-9]{40}$',re.IGNORECASE)\n if p.search(f) is not None:\n if not f in results:\n results.append(f)\n \n dfs = []\n\n # if we did not get any machine Ids, treat them as ComputerDnsNames\n if len(results) == 0:\n results = cell.split('\\n')\n for hostname in results:\n dfs.append(MsftGraphSec_api.machines(filterstr=\"$filter=ComputerDnsName eq '%s'\" % hostname))\n else:\n for machine_id in results:\n dfs.append(MsftGraphSec_api.machines(machineid=machine_id))\n import pandas as pd\n return pd.concat(dfs)\n \n# Delete these to avoid name conflicts for automagic to work\ndel graph_sec_machine \n\n@register_line_cell_magic\ndef graph_sec_alert(line, cell=None):\n if cell is None:\n return MsftGraphSec_api.alerts(alertid=line)\n else: \n results = []\n for f in re.split(SPLIT_DELIMS,cell):\n p = re.compile('^[{(]?[0-9A-F]{8}[-]?(?:[0-9A-F]{4}[-]?){3}[0-9A-F]{12}[)}]?$',re.IGNORECASE)\n if p.search(f) is not None:\n if not f in results:\n results.append(f)\n if len(results) == 0:\n return\n dfs = []\n for alert_id in results:\n dfs.append(MsftGraphSec_api.alerts(alertid=alert_id))\n import pandas as pd\n return pd.concat(dfs)\n\n# Delete these to avoid name conflicts for automagic to work\ndel graph_sec_alert \n\n@register_line_cell_magic\ndef graph_sec_ip(line, cell=None):\n if cell is None:\n return MsftGraphSec_api.ips(ip=line)\n else: \n results = []\n for f in re.split(SPLIT_DELIMS,cell):\n p = re.compile('^\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}$')\n if p.search(f) is not None:\n if not f in results:\n results.append(f)\n if len(results) == 0:\n return\n dfs = []\n for ip in results:\n dfs.append(MsftGraphSec_api.ips(ip=ip))\n import pandas as pd\n return pd.concat(dfs)\n \n# Delete these to avoid name conflicts for automagic to work\ndel graph_sec_ip \n \n@register_line_cell_magic\ndef graph_sec_action(line, cell=None):\n if cell is None:\n return MsftGraphSec_api.ips(ip=line)\n else: \n results = []\n for f in re.split(SPLIT_DELIMS,cell):\n p = re.compile('^[a-f0-9]{8}'\n '-[a-f0-9]{4}'\n '-[a-f0-9]{4}'\n '-[a-f0-9]{4}'\n '-[a-f0-9]{12}$'\n ,re.IGNORECASE)\n if p.search(f) is not None:\n if not f in results:\n results.append(f)\n if len(results) == 0:\n return\n dfs = []\n for action in results:\n dfs.append(MsftGraphSec_api.machine_actions(actionid = action))\n import pandas as pd\n return pd.concat(dfs)\n \n# Delete these to avoid name conflicts for automagic to work\ndel graph_sec_action\n\n \nclass MicrosoftGraphSecurityAPI:\n def __init__(self, tenantId, appId, appSecret, vt_api_key=None, fUsePandas=True, \n api_root=\"https://graph.microsoft.com/\", api_version=\"v1.0\"):\n url = \"https://login.microsoftonline.com/%s/oauth2/v2.0/token\" % (tenantId)\n\n self.fDebug = False\n\n body = {\n 'client_id' : appId,\n 'client_secret' : appSecret,\n 'grant_type' : 'client_credentials',\n 'scope': 'https://graph.microsoft.com/.default'\n }\n\n ## authenticate and obtain AAD Token for future calls\n data = urllib.parse.urlencode(body).encode(\"utf-8\")\n req = urllib.request.Request(url, data)\n response = urllib.request.urlopen(req)\n jsonResponse = json.loads(response.read().decode())\n self.aadToken = jsonResponse[\"access_token\"]\n self.headers = { \n 'Content-Type' : 'application/json',\n 'Accept' : 'application/json',\n 'Authorization' : \"Bearer \" + self.aadToken\n }\n self.fUsePandas = fUsePandas # use pandas DataFrame for collections of objects, else return a list\n self.api_root = api_root + api_version \n self.vt_api_key = vt_api_key\n if len(self.aadToken) > 0:\n print(\"Connected.\")\n \n def set_output_type(self, fUsePandas=True):\n self.fUsePandas = fUsePandas \n\n def set_debug_output(self, fDebug=True):\n self.fDebug = fDebug \n \n def __validate_arguments(self,args, valid_params):\n if len(args) == 0:\n raise ValueError ('argument must be one of %s' % str(list(valid_params.keys())))\n elif len(args) > 1:\n raise ValueError ('only one id can be used at a time')\n else:\n selector = next(iter(args))\n selector_value= next(iter(args.values()))\n if selector not in list(valid_params.keys()):\n raise ValueError ('argument must be one of %s' % str(list(valid_params.keys())))\n return (selector, selector_value)\n\n def __make_request(self,url, params=None):\n \n if self.fDebug:\n print(url)\n req = urllib.request.Request(url, headers=self.headers)\n try:\n response = urllib.request.urlopen(req)\n except urllib.error.HTTPError as e:\n print(e.code)\n if e.code == 404:\n response = e\n else:\n raise e\n \n jsonResponse = json.loads(response.read().decode())\n if type(jsonResponse) == int:\n if self.fUsePandas:\n return pd.DataFrame([jsonResponse])\n else:\n return jsonResponse\n if 'value' in jsonResponse:\n res = jsonResponse[\"value\"]\n if len(res) == 0:\n res = {}\n else:\n res = jsonResponse \n if self.fUsePandas:\n return pd.io.json.json_normalize(res)\n return res\n\n def __prepare_param_dict_from_filter_str(self, filterstr):\n get_params = {}\n for filter_param in re.split(\"[\\?\\&]+\", filterstr):\n if len(filter_param)> 0:\n attr = filter_param.split('=')[0]\n val = filter_param.split('=')[1]\n get_params[attr]= val\n return get_params\n \n def __get_json_alert(self, alertid=None):\n _pandas = self.fUsePandas\n self.fUsePandas = False\n alert_as_json = self.alerts(alertid=alertid)\n self.fUsePandas = _pandas\n return alert_as_json\n \n def alerts(self, **kwargs):\n alert_url = self.api_root + \"/security/alerts\"\n get_params = None\n \n valid_params = {\n 'filterstr' : alert_url + '?%s',\n 'alertid' : alert_url + '/%s',\n 'userid' : alert_url + \"?$filter=userStates/any(d:d/userPrincipalName eq '%s')\",\n 'ip' : alert_url + \"?$filter=hostStates/any(d:d/privateIpAddress eq '%s')\",\n 'hostfqdn' : alert_url + \"?$filter=hostStates/any(d:d/fqdn eq '%s')\", \n 'filehash' : alert_url + \"?$filter=fileStates/any(d:d/fileHash/hashValue eq '%s')\",\n 'filename' : alert_url + \"?$filter=fileStates/any(d:d/name eq '%s')\", \n 'domain' : alert_url + \"?$filter=networkConnections/any(d:d/destinationDomain eq '%s')\" \n }\n (selector, selector_value) = self.__validate_arguments(kwargs, valid_params)\n \n if selector == 'filterstr':\n get_params = self.__prepare_param_dict_from_filter_str(selector_value)\n if get_params is not None:\n url = valid_params[selector] % urllib.parse.urlencode(get_params)\n else:\n url = valid_params[selector] % selector_value\n url = urllib.parse.quote( url , safe=\"%/:=&?~#+!$,;'@()*[]\") # Url encode spaces \n\n return self.__make_request(url)\n \n def update_alert(self, alertid=None, alertbody=None):\n import requests \n\n alert_url = self.api_root + \"/security/alerts\"\n \n valid_params = {\n 'alertid' : alert_url + '/%s'\n }\n (selector, selector_value) = self.__validate_arguments({\"alertid\": alertid}, valid_params)\n \n if alertbody == None:\n raise ValueError ('Request body cannot be empty')\n \n headers = self.headers\n headers['Prefer'] = \"return=representation\"\n \n _old_alert = self.__get_json_alert(alertid=alertid) \n \n alertbody[\"vendorInformation\"] = _old_alert[\"vendorInformation\"] # vendorInformation is required to PATCH an alert\n \n url = valid_params[selector] % selector_value\n json_body = json.dumps(alertbody)\n response = requests.patch(url, json_body, headers=headers)\n\n jsonResponse = response.json()\n\n if self.fUsePandas:\n return pd.io.json.json_normalize(jsonResponse)\n return jsonResponse\n\n\n \n def users(self, **kwargs):\n user_url = self.api_root + \"/users\"\n \n valid_params = {\n 'userid' : user_url + '/%s'\n }\n \n (selector, selector_value) = self.__validate_arguments(kwargs, valid_params)\n \n url = valid_params[selector] % selector_value\n\n return self.__make_request(url)\n \n \n def vtresults(self, hashlist):\n import requests \n\n url = \"https://www.virustotal.com/vtapi/v2/file/report\"\n\n headers = {'User-Agent':'VirusTotal',\n 'Content-Type':'application/json'}\n if type(hashlist) == str:\n hashlist = [hashlist]\n \n data = {\"resource\": ','.join(hashlist),\n \"apikey\": self.vt_api_key}\n\n response = requests.get(url, data, headers=headers)\n\n jsonResponse = response.json()\n\n if self.fUsePandas:\n return pd.io.json.json_normalize(jsonResponse)\n return r.json()\n \nprint(\"Sample Microsoft Graph Security API code loaded\")",
- "execution_count": null,
- "outputs": []
- },
- {
- "metadata": {
- "trusted": true
- },
- "cell_type": "code",
- "source": "# hit Shift-Enter in this cell\n\n# NOTE: endpoint authorization will periodically time out and you will need to re-run this command to re-authenticate\n# if you're able to call the API (client app registered properly), and you get an exception \n# with a HTTP error 401 Unauthorized, re-run this command to re-initiate the endpoint\n\nMsftGraphSec_api = MicrosoftGraphSecurityAPI(tenantId, appId, appSecret, vt_api_key)\nMsftGraphSec_api.set_debug_output()",
- "execution_count": null,
- "outputs": []
- },
- {
- "metadata": {},
- "cell_type": "markdown",
- "source": "# Get Alerts\n\nLet's query the most recent 5 alerts using the OData TOP keyword. The `$top=5` query will return 5 of the most recent alerts from *each* [Microsoft Graph Security alert provider](https://aka.ms/graphsecurityalerts). "
- },
- {
- "metadata": {
- "trusted": true
- },
- "cell_type": "code",
- "source": "MsftGraphSec_api.alerts(filterstr = \"$top=5\")",
- "execution_count": null,
- "outputs": []
- },
- {
- "metadata": {},
- "cell_type": "markdown",
- "source": "# Security Management and Monitoring Scenarios\n## List high severity alerts \nYou can [query alerts](https://docs.microsoft.com/en-us/graph/api/alert-list?view=graph-rest-1.0) with OData queries. OData provides a simple standardized syntax for selecting properties and filtering data\n\nA summary of the OData filters can be found [here](https://docs.microsoft.com/graph/query-parameters) "
- },
- {
- "metadata": {
- "trusted": true
- },
- "cell_type": "code",
- "source": "# get the top high-sev 5 alerts and select a few columns \nMsftGraphSec_api.alerts(filterstr = \"$select=createdDateTime,category,title,description,id,severity,assignedTo&$filter=Severity eq 'High'&$top=5\")",
- "execution_count": null,
- "outputs": []
- },
- {
- "metadata": {},
- "cell_type": "markdown",
- "source": "## Analyzing Security Data \n\nThe results are returned as a Pandas DataFrame--a handy data structure for processing rowset oriented results. If you don't want the results in a DataFrame and instead just in a list, you can set `fUsePandas=False` when you create the MicrosoftGraphSecurityAPI class.\n\nSee the [Pandas project page](https://pandas.pydata.org/pandas-docs/stable/index.html) for more information on DataFrames."
- },
- {
- "metadata": {
- "trusted": true
- },
- "cell_type": "code",
- "source": "# let's assign the API results to a variable so we can process them without making an API call each time\ndf = MsftGraphSec_api.alerts(filterstr = \"$top=25&$filter=Severity eq 'High'\")\nprint(\"number of rows returned = %d\" % len(df))",
- "execution_count": null,
- "outputs": []
- },
- {
- "metadata": {
- "trusted": true
- },
- "cell_type": "code",
- "source": "# show all the columns in the alert entity\ndf.columns",
- "execution_count": null,
- "outputs": []
- },
- {
- "metadata": {
- "trusted": true
- },
- "cell_type": "code",
- "source": "# Let's select just the columns we want to view. This uses the Pandas syntax for selecting columns\n\ndf[['createdDateTime','category','description','id','severity']].head(5)",
- "execution_count": null,
- "outputs": []
- },
- {
- "metadata": {
- "trusted": true
- },
- "cell_type": "code",
- "source": "# let's group them by title and count their frequency\ndf1 = df[['id','title']].groupby('title').count().rename(index=str, columns={\"id\":\"Alert Count\"})\ndf1 = df1.sort_values(['Alert Count'], ascending=False)\ndf1",
- "execution_count": null,
- "outputs": []
- },
- {
- "metadata": {
- "trusted": true
- },
- "cell_type": "code",
- "source": "# show a quick pie chart using matplotlib\n%matplotlib inline\nplt = df1.plot.pie(y=0, figsize=(5, 5), legend=False, autopct='%1.0f%%')",
- "execution_count": null,
- "outputs": []
- },
- {
- "metadata": {},
- "cell_type": "markdown",
- "source": "# Security Investigation Scenarios\n## Querying alerts by UPN (User Principal Name)"
- },
- {
- "metadata": {
- "trusted": true
- },
- "cell_type": "code",
- "source": "MsftGraphSec_api.alerts( userid = '<>')",
- "execution_count": null,
- "outputs": []
- },
- {
- "metadata": {},
- "cell_type": "markdown",
- "source": "## Querying alerts by machine FQDNs (Fully Qualified Domain Name)\nYou can query alerts by machine fqdn, user id, ip, alert id, file sha1, domain, OData query, and more"
- },
- {
- "metadata": {
- "trusted": true
- },
- "cell_type": "code",
- "source": "MsftGraphSec_api.alerts( hostfqdn = '<>')",
- "execution_count": null,
- "outputs": []
- },
- {
- "metadata": {
- "trusted": true
- },
- "cell_type": "code",
- "source": "# query machines associated with an alert\nMsftGraphSec_api.alerts( alertid = '<>')[['id', 'hostStates']] #[['id', 'osBuild','osPlatform']]",
- "execution_count": null,
- "outputs": []
- },
- {
- "metadata": {
- "trusted": true
- },
- "cell_type": "code",
- "source": "# query alerts by machine name\nMsftGraphSec_api.alerts( filterstr = \"$filter=hostStates/any(d:d/netBiosName eq '<>')\")",
- "execution_count": null,
- "outputs": []
- },
- {
- "metadata": {},
- "cell_type": "markdown",
- "source": "# Using different Data accesses\n\n## Data access using Jupyter Magics\n\nLines starting with % signify a Jupyter magic. A \"line magic\" take the text after the command and does something with it. This notebook defines several magics to make it easier to access the data you need.\n\n### Use magic on alert (entity)\n\n`%graph_sec_alert` takes an alert id and calls the API to get details about it"
- },
- {
- "metadata": {
- "trusted": true,
- "scrolled": true
- },
- "cell_type": "code",
- "source": "%graph_sec_alert <>",
- "execution_count": null,
- "outputs": []
- },
- {
- "metadata": {},
- "cell_type": "markdown",
- "source": "#### Querying multiple alerts and regex\nYou can also provide a list of alert ids and invoke the cell magic with `%%graph_sec_alert`\n\nBecause alert ids have a standard syntax, the alert magic also can take arbitrary text and it will extract alert ids\nby using a regex. This is handy if you want to quickly copy-paste some text from an email or chat window that has\nalert ids intermixed with conversation."
- },
- {
- "metadata": {
- "trusted": true
- },
- "cell_type": "code",
- "source": "%%graph_sec_alert\nHi, be sure to investigate these 3 alerts and verify your results.\nD3EC9E2C-29A2-4DD3-9E1E-068C9B022938\n41CB1B5D-F295-40B3-8B18-DFC4AA85531E\nAD5D3084-CB9A-45D5-9AA0-81EF680C20D4\nPlease update the ticket when completed,\nThanks! ",
- "execution_count": null,
- "outputs": []
- },
- {
- "metadata": {},
- "cell_type": "markdown",
- "source": "### Use Magic for properties like files\nYou can look up Microsoft Graph Security alert data on files with the `%%graph_sec_file` magic by passing the file hash value"
- },
- {
- "metadata": {
- "trusted": true,
- "scrolled": true
- },
- "cell_type": "code",
- "source": "%%graph_sec_file \n<>\n",
- "execution_count": null,
- "outputs": []
- }
- ],
- "metadata": {
- "kernelspec": {
- "name": "python36",
- "display_name": "Python 3.6",
- "language": "python"
- },
- "language_info": {
- "mimetype": "text/x-python",
- "nbconvert_exporter": "python",
- "name": "python",
- "pygments_lexer": "ipython3",
- "version": "3.6.6",
- "file_extension": ".py",
- "codemirror_mode": {
- "version": 3,
- "name": "ipython"
- }
- }
- },
- "nbformat": 4,
- "nbformat_minor": 2
-}
\ No newline at end of file
diff --git a/Notebooks/Python/Microsoft/Security/Microsoft Graph/Security Monitoring Scenarios.ipynb b/Notebooks/Python/Microsoft/Security/Microsoft Graph/Security Monitoring Scenarios.ipynb
deleted file mode 100644
index 7fb3ca4..0000000
--- a/Notebooks/Python/Microsoft/Security/Microsoft Graph/Security Monitoring Scenarios.ipynb
+++ /dev/null
@@ -1,177 +0,0 @@
-{
- "cells": [
- {
- "metadata": {},
- "cell_type": "markdown",
- "source": "# Introduction\nThis notebook shows how to use the [Microsoft Graph Security API](https://aka.ms/graphsecuritydocs). It defines a Python wrapper for calling the API to make it easy to access [Microsoft Graph Security alerts](https://aka.ms/graphsecurityalerts). While the APIs are documented and supported,\nthe wrapper in this notebook is a sample and is not an official programming interface.\n\nAuthor: [Microsoft Graph Security Team](graphsecfeedback@microsoft.com) (Inspired by [@JohnLaTwC](https://twitter.com/JohnLaTwC))\n\n## Links to Microsoft Graph Security API documentation and other samples\n\n[Overview of Microsoft Graph Security](https://aka.ms/graphsecuritydocs)\n\n[What are alerts?](https://aka.ms/graphsecurityalerts)\n\n[Alert Schema - list of properties and descriptions](https://docs.microsoft.com/en-us/graph/api/resources/alert?view=graph-rest-1.0) \n\n[Authorization - Application-only and User-Delegated](https://docs.microsoft.com/graph/security-authorization?view=graph-rest-1.0)\n\n[More Samples](https://aka.ms/graphsecurityapicode)\n\n[OData query examples](https://docs.microsoft.com/graph/query-parameters)"
- },
- {
- "metadata": {},
- "cell_type": "markdown",
- "source": "# Authentication - Initialize secrets\n\nDownload this notebook and follow the steps below to get the application ID and secret that you can use to authenticate and get data from your Azure Active Directory (Azure AD) tenant using this notebook. \n1.\t[Register your application](https://docs.microsoft.com/en-us/graph/auth-v2-service#1-register-your-app) for this notebook in Azure AD in application only mode. \n2.\t[Configure permissions](https://docs.microsoft.com/en-us/graph/auth-v2-service#2-configure-permissions-for-microsoft-graph) and be sure to add the `SecurityEvents.ReadWrite.All` permission to your application.\n3. Get your Azure AD tenant administrator to [grant tenant administration consent](https://docs.microsoft.com/en-us/graph/auth-v2-service#3-get-administrator-consent) to your application. This is a one-time activity unless permissions change for the application. \n\nWhen your app is registered to call the Microsoft Graph Security API you need to pass the application ID and application secret from the above mentioned steps in to this sample. \n\nUse either plain text input to enter your secret in the `get_secret` function or get it from your environment variable in the `get_secret` function below the first one. Use only one of these functions to get secret. "
- },
- {
- "metadata": {
- "trusted": true
- },
- "cell_type": "code",
- "source": "def get_secret(secret_name):\n return {'GRAPHSEC_DEMO_appId':'<>',\n 'GRAPHSEC_DEMO_appSecret':'<>',\n 'GRAPHSEC_DEMO_tenantId':'<>'}[secret_name]",
- "execution_count": null,
- "outputs": []
- },
- {
- "metadata": {
- "trusted": true
- },
- "cell_type": "code",
- "source": "## e.g. custom way to access secrets\ndef get_secret(secret_name):\n import os\n return os.environ.get(secret_name)",
- "execution_count": null,
- "outputs": []
- },
- {
- "metadata": {
- "trusted": true
- },
- "cell_type": "code",
- "source": "appId = get_secret('GRAPHSEC_DEMO_appId')\nappSecret = get_secret('GRAPHSEC_DEMO_appSecret') \ntenantId = get_secret('GRAPHSEC_DEMO_tenantId')\nprint(\"If your secrets were initialized properly you should see your tenant id.\\nTenant Id: %s \" % tenantId)",
- "execution_count": null,
- "outputs": []
- },
- {
- "metadata": {},
- "cell_type": "markdown",
- "source": "# Getting Started\nAll the API Wrapper code is below. Activate it by clicking in the cell and hitting Shift+Enter"
- },
- {
- "metadata": {
- "trusted": true
- },
- "cell_type": "code",
- "source": "# -------------------------------------------------------------------------\n# Copyright (c) Microsoft Corporation. All rights reserved.\n# Licensed under the MIT License. \n# --------------------------------------------------------------------------\n\n## https://aka.ms/graphsecuritydocs\n\nimport json\nimport urllib.request\nimport urllib.parse\nimport pandas as pd\nimport re\n\n \nclass MicrosoftGraphSecurityAPI:\n def __init__(self, tenantId, appId, appSecret, fUsePandas=True, \n api_root=\"https://graph.microsoft.com/\", api_version=\"v1.0\"):\n url = \"https://login.microsoftonline.com/%s/oauth2/v2.0/token\" % (tenantId)\n\n self.fDebug = False\n\n body = {\n 'client_id' : appId,\n 'client_secret' : appSecret,\n 'grant_type' : 'client_credentials',\n 'scope': 'https://graph.microsoft.com/.default'\n }\n\n ## authenticate and obtain AAD Token for future calls\n data = urllib.parse.urlencode(body).encode(\"utf-8\")\n req = urllib.request.Request(url, data)\n response = urllib.request.urlopen(req)\n jsonResponse = json.loads(response.read().decode())\n self.aadToken = jsonResponse[\"access_token\"]\n self.headers = { \n 'Content-Type' : 'application/json',\n 'Accept' : 'application/json',\n 'Authorization' : \"Bearer \" + self.aadToken\n }\n self.fUsePandas = fUsePandas # use pandas DataFrame for collections of objects, else return a list\n self.api_root = api_root + api_version\n if len(self.aadToken) > 0:\n print(\"Connected.\")\n \n def set_output_type(self, fUsePandas=True):\n self.fUsePandas = fUsePandas \n\n def set_debug_output(self, fDebug=True):\n self.fDebug = fDebug \n \n def __validate_arguments(self,args, valid_params):\n if len(args) == 0:\n raise ValueError ('argument must be one of %s' % str(list(valid_params.keys())))\n elif len(args) > 1:\n raise ValueError ('only one id can be used at a time')\n else:\n selector = next(iter(args))\n selector_value= next(iter(args.values()))\n if selector not in list(valid_params.keys()):\n raise ValueError ('argument must be one of %s' % str(list(valid_params.keys())))\n return (selector, selector_value)\n\n def __make_request(self,url, params=None):\n \n if self.fDebug:\n print(url)\n req = urllib.request.Request(url, headers=self.headers)\n try:\n response = urllib.request.urlopen(req)\n except urllib.error.HTTPError as e:\n raise e\n \n jsonResponse = json.loads(response.read().decode())\n if type(jsonResponse) == int:\n if self.fUsePandas:\n return pd.DataFrame([jsonResponse])\n else:\n return jsonResponse\n if 'value' in jsonResponse:\n res = jsonResponse[\"value\"]\n if len(res) == 0:\n res = {}\n else:\n res = jsonResponse \n if self.fUsePandas:\n return pd.io.json.json_normalize(res)\n return res\n\n def __prepare_param_dict_from_filter_str(self, filterstr):\n get_params = {}\n for filter_param in re.split(\"[\\?\\&]+\", filterstr):\n if len(filter_param)> 0:\n attr = filter_param.split('=')[0]\n val = filter_param.split('=')[1]\n get_params[attr]= val\n return get_params\n \n def alerts(self, **kwargs):\n alert_url = self.api_root + \"/security/alerts\"\n get_params = None\n \n valid_params = {\n 'filterstr' : alert_url + '?%s',\n 'alertid' : alert_url + '/%s',\n 'userid' : alert_url + \"?$filter=userStates/any(d:d/userPrincipalName eq '%s')\",\n 'ip' : alert_url + \"?$filter=hostStates/any(d:d/privateIpAddress eq '%s')\",\n 'hostfqdn' : alert_url + \"?$filter=hostStates/any(d:d/fqdn eq '%s')\", \n 'filehash' : alert_url + \"?$filter=fileStates/any(d:d/fileHash/hashValue eq '%s')\",\n 'filename' : alert_url + \"?$filter=fileStates/any(d:d/name eq '%s')\", \n 'domain' : alert_url + \"?$filter=networkConnections/any(d:d/destinationDomain eq '%s')\" \n }\n (selector, selector_value) = self.__validate_arguments(kwargs, valid_params)\n \n if selector == 'filterstr':\n get_params = self.__prepare_param_dict_from_filter_str(selector_value)\n if get_params is not None:\n url = valid_params[selector] % urllib.parse.urlencode(get_params)\n else:\n url = valid_params[selector] % selector_value\n url = urllib.parse.quote( url , safe=\"%/:=&?~#+!$,;'@()*[]\") # Url encode spaces \n\n return self.__make_request(url)\n \nprint(\"Sample Microsoft Graph Security API code loaded\")",
- "execution_count": null,
- "outputs": []
- },
- {
- "metadata": {
- "trusted": true
- },
- "cell_type": "code",
- "source": "# hit Shift-Enter in this cell\n\n# NOTE: endpoint authorization will periodically time out and you will need to re-run this command to re-authenticate\n# if you're able to call the API (client app registered properly), and you get an exception \n# with a HTTP error 401 Unauthorized, re-run this command to re-initiate the endpoint\n\nMsftGraphSec_api = MicrosoftGraphSecurityAPI(tenantId, appId, appSecret)\nMsftGraphSec_api.set_debug_output()",
- "execution_count": null,
- "outputs": []
- },
- {
- "metadata": {},
- "cell_type": "markdown",
- "source": "# Testing Get Alerts\n\nLet's query the most recent 5 alerts using the OData TOP keyword. The `$top=5` query will return 5 of the most recent alerts from **each** [Microsoft Graph Security alert provider](https://aka.ms/graphsecurityalerts). "
- },
- {
- "metadata": {
- "trusted": true
- },
- "cell_type": "code",
- "source": "MsftGraphSec_api.alerts(filterstr = \"$top=5\")",
- "execution_count": null,
- "outputs": []
- },
- {
- "metadata": {},
- "cell_type": "markdown",
- "source": "# Security Management and Monitoring Scenarios\n## List high severity alerts \nYou can [query alerts](https://docs.microsoft.com/en-us/graph/api/alert-list?view=graph-rest-1.0) with OData queries. OData provides a simple standardized syntax for selecting properties and filtering data\n\nA summary of the OData filters can be found [here](https://docs.microsoft.com/graph/query-parameters) "
- },
- {
- "metadata": {
- "trusted": true
- },
- "cell_type": "code",
- "source": "# get the top high-sev 5 alerts and select a few columns \nMsftGraphSec_api.alerts(filterstr = \"$select=createdDateTime,category,title,description,id,severity,assignedTo&$filter=Severity eq 'High'&$top=5\")",
- "execution_count": null,
- "outputs": []
- },
- {
- "metadata": {},
- "cell_type": "markdown",
- "source": "## Analyzing Security Data \n\nThe results are returned as a Pandas DataFrame--a handy data structure for processing rowset oriented results. If you don't want the results in a DataFrame and instead just in a list, you can set `fUsePandas=False` when you create the MicrosoftGraphSecurityAPI class.\n\nSee the [Pandas project page](https://pandas.pydata.org/pandas-docs/stable/index.html) for more information on DataFrames."
- },
- {
- "metadata": {
- "trusted": true
- },
- "cell_type": "code",
- "source": "# let's assign the API results to a variable so we can process them without making an API call each time\ndf = MsftGraphSec_api.alerts(filterstr = \"$top=25&$filter=Severity eq 'High'\")\nprint(\"number of rows returned = %d\" % len(df))",
- "execution_count": null,
- "outputs": []
- },
- {
- "metadata": {
- "trusted": true
- },
- "cell_type": "code",
- "source": "# show all the columns in the alert entity\ndf.columns",
- "execution_count": null,
- "outputs": []
- },
- {
- "metadata": {
- "trusted": true
- },
- "cell_type": "code",
- "source": "# Let's select just the columns we want to view. This uses the Pandas syntax for selecting columns\n\ndf[['createdDateTime','category','description','id','severity']].head(5)",
- "execution_count": null,
- "outputs": []
- },
- {
- "metadata": {
- "trusted": true
- },
- "cell_type": "code",
- "source": "# let's group them by title and count their frequency\ndf1 = df[['id','title']].groupby('title').count().rename(index=str, columns={\"id\":\"Alert Count\"})\ndf1 = df1.sort_values(['Alert Count'], ascending=False)\ndf1",
- "execution_count": null,
- "outputs": []
- },
- {
- "metadata": {
- "trusted": true
- },
- "cell_type": "code",
- "source": "# show a quick pie chart using matplotlib\n%matplotlib inline\nplt = df1.plot.pie(y=0, figsize=(5, 5), legend=False, autopct='%1.0f%%')",
- "execution_count": null,
- "outputs": []
- },
- {
- "metadata": {},
- "cell_type": "markdown",
- "source": "## Querying alerts by alert id"
- },
- {
- "metadata": {
- "trusted": true
- },
- "cell_type": "code",
- "source": "MsftGraphSec_api.alerts( alertid=\"<>\" )",
- "execution_count": null,
- "outputs": []
- }
- ],
- "metadata": {
- "kernelspec": {
- "name": "python36",
- "display_name": "Python 3.6",
- "language": "python"
- },
- "language_info": {
- "mimetype": "text/x-python",
- "nbconvert_exporter": "python",
- "name": "python",
- "pygments_lexer": "ipython3",
- "version": "3.6.6",
- "file_extension": ".py",
- "codemirror_mode": {
- "version": 3,
- "name": "ipython"
- }
- }
- },
- "nbformat": 4,
- "nbformat_minor": 2
-}
\ No newline at end of file
diff --git a/requirements.txt b/requirements.txt
index 0905c87..cded26c 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,5 +1,7 @@
numpy
matplotlib
+pandas
+scipy
ipywidgets
jupyter_contrib_nbextensions
jupyterthemes
| | | |