diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..dfe0770 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +# Auto detect text files and perform LF normalization +* text=auto diff --git a/Dockerfile b/Dockerfile index 83ab83a..d33e23b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,10 @@ FROM jupyter/base-notebook:latest +RUN python -m pip install --upgrade pip +COPY requirements.txt ./requirements.txt +RUN python -m pip install -r requirements.txt +RUN python -m pip install --upgrade --no-deps --force-reinstall notebook + ARG NB_USER=jovyan ARG NB_UID=1000 ENV USER ${NB_USER} @@ -34,7 +39,7 @@ RUN rm -rf $ANACONDA_HOME/envs/$CONDA_DEFAULT_ENV/share/jupyter ## Install necessary packages RUN apt-get update -RUN apt-get install -y build-essential curl apt-utils git +RUN apt-get install -y build-essential curl apt-utils ENV \ # Enable detection of running in a container @@ -89,7 +94,7 @@ USER ${USER} # Install Jupyterlab with extensions RUN echo "${YELLOW}Installing/Updating Jupyter Lab and all required packages" -RUN pip install --upgrade pip tornado jupyterlab jupyterlab-git nbdime nteract_on_jupyter elyra +RUN pip install --upgrade pip tornado jupyterlab jupyterlab-git nbdime nteract_on_jupyter # Rebuild Jupyter Lab and relaunch after install. Reason for this is jupyterlab-git doesn't seem to work without building jupyyterlab prior to launching app RUN echo "Rebuilding Jupyter lab... THIS WILL TAKE A WHILE! GET SOME COFFEE${NC}" @@ -131,7 +136,7 @@ WORKDIR ${HOME}/Notebooks/ ################################################# ## Runs Jupyter Lab on port 8888 and enables sudo to install packages -CMD jupyter lab --ip=* --port=8888 --no-browser --allow-root +#CMD jupyter lab --ip=* --port=8888 --no-browser --allow-root # --allow-root -e GRANT_SUDO=yes --user jovyan # to run diff --git a/Notebooks/PowerShell/01-Getting-Started-README.ipynb b/Notebooks/PowerShell/01-Getting-Started-README.ipynb deleted file mode 100755 index cc7ac7a..0000000 --- a/Notebooks/PowerShell/01-Getting-Started-README.ipynb +++ /dev/null @@ -1,466 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Getting Started Guide" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Keyboard Shortcuts" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "heading_collapsed": "true" - }, - "source": [ - "### Navigating Jupyter Notebooks Cells\n", - "Press up and down to move between cells. Press [Enter] to enter a cell and edit it. Press [Esc] to exit the cell." - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "\r\n", - "
\r\n", - " \r\n", - " \r\n", - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Cell 1: Arrow up to me\n" - ] - } - ], - "source": [ - "\"Cell 1: Arrow up to me\"" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "\"Cell 2\"" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "\"Cell 3: Arrow down to Me\"" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Running Content for selected cell\n", - "Select cell by pressing [Enter] and run the selected cell by pressing the keyboard combination [Shift]+[Enter]. You can run a cell just by having it highlighted" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "\r\n", - "
\r\n", - " \r\n", - " \r\n", - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\u001b[93mGetting list of Processes\u001b[0m\n", - "\n", - " NPM(K) PM(M) WS(M) CPU(s) Id SI ProcessName\n", - " ------ ----- ----- ------ -- -- -----------\n", - " 158 403.90 334.79 138.41 5852 0 ApplicationProxyConnectorService\n", - " 26 48.20 42.69 0.77 6032 0 ApplicationProxyConnectorUpdaterService\n", - " 9 2.90 7.86 0.52 3152 2 conhost\n", - " 11 5.43 16.52 0.83 6008 2 conhost\n", - " 11 5.45 13.64 0.05 6848 2 conhost\n", - "\n" - ] - } - ], - "source": [ - "Write-Host -foreground yellow \"Getting list of Processes\"\n", - "Get-Process | select -First 5 | % { start-sleep -Milliseconds 300; $_ }" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Inserting, Modifying Cell, Deleting Cell\n", - "- Insert Above: Press [A] to insert a new cell above the current cell\n", - "- Insert Below: [B] to insert a new cell below.\n", - "- Press [D] twice to delete" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Cell 1\n" - ] - } - ], - "source": [ - "\"Cell 1\"" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "\"Cell 2\"" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Cell 3 - Add a cell below me with [B] and then press '[D][D]' to delete it\n" - ] - } - ], - "source": [ - "\"Cell 3 - Add a cell below me with [B] and then press '[D][D]' to delete it\"" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Shift + Tab will show you the Docstring (documentation) for the the object you have just typed in a code cell – you can keep pressing this short cut to cycle through a few modes of documentation." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Changing the Cell Type\n", - "- Markup Cell - Press [M] to change the current cell to Markup Language.\n", - "- Code - Press [Y] to change the current cell to Code" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "This cell should be a markup language\n" - ] - } - ], - "source": [ - "\"This cell should be a markup language\"" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "heading_collapsed": "true" - }, - "source": [ - "## Pound signs indicates headers. The more pounds = the smaller the header\n", - "\n", - "\"Change me to either Markup language or Code by pressing M or Y. Then press shift-enter to convert the markup language\"" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Ctrl + Shift + - will split the current cell into two from where your cursor is." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Hold shift and press down or up" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Ctrl + Shift + - will split the current cell into two from where your cursor is." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Hold shift and press down or up" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Ctrl + Shift + - will split the current cell into two from where your cursor is." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### The command Palette\n", - "Another way to access keyboard shortcuts, and a handy way to learn them is to use the command palette.\n", - "\n", - "- Windows or Linux\n", - "[Ctrl] + [Shift] + [C] on Linux and Windows)\n", - " \n", - "- Apple\n", - "[Cmd] + [Shift] + [P or C]" - ] - } - ], - "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/02-HelloWorld.ipynb b/Notebooks/PowerShell/02-HelloWorld.ipynb deleted file mode 100755 index 9eb98e0..0000000 --- a/Notebooks/PowerShell/02-HelloWorld.ipynb +++ /dev/null @@ -1,236 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "id": "professional-toronto", - "metadata": {}, - "source": [ - "# Test if it works" - ] - }, - { - "cell_type": "markdown", - "id": "typical-seminar", - "metadata": {}, - "source": [ - "## Hello World Test" - ] - }, - { - "cell_type": "markdown", - "id": "collaborative-footage", - "metadata": {}, - "source": [ - "Press down to this cell and press \"shift\" + \"enter\"" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "id": "martial-moscow", - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "\r\n", - "
\r\n", - " \r\n", - " \r\n", - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Hello World\n" - ] - } - ], - "source": [ - "Write-Host \"Hello World\";" - ] - }, - { - "cell_type": "markdown", - "id": "dramatic-approval", - "metadata": {}, - "source": [ - "## Run this to see the picture" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "id": "apart-narrow", - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "\n", - "\n", - "\n", - "

via GIPHY

" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "#!html\n", - "\n", - "\n", - "

via GIPHY

" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "finite-condition", - "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-showcode": false, - "toc-showmarkdowntxt": false, - "toc-showtags": false - }, - "nbformat": 4, - "nbformat_minor": 5 -} diff --git a/Notebooks/PowerShell/1 - Tutorial with Videos/Chapter 01 - Getting started with PowerShell.ipynb b/Notebooks/PowerShell/1 - Tutorial with Videos/Chapter 01 - Getting started with PowerShell.ipynb deleted file mode 100755 index 1547f41..0000000 --- a/Notebooks/PowerShell/1 - Tutorial with Videos/Chapter 01 - Getting started with PowerShell.ipynb +++ /dev/null @@ -1,782 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Chapter 1 - Getting started with Powershell" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "- This tutorial was sourced from the great work done by http://GoalKicker.com/PowerShellBook and the content is written by the beautiful people at Stack Overflow.\n", - "\n", - "Table of Contents
\n", - "1. [Allow scripts stored on your machine to run unsigned](#1)\n", - "2. [Aliases & Similar Functions](#2)\n", - "3. [The Pipeline - Using Output from a PowerShell cmdlet](#3)\n", - "4. [Calling .Net Library Methods](#4)\n", - "5. [Installation or Setup](#5)\n", - "6. [Commenting](#6)\n", - "7. [Creating Objects](#7)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Allow scripts stored on your machine to run unsigned\n", - "\n", - "#### TechNet Documentation:\n", - "[Set-ExecutionPolicy](https://technet.microsoft.com/en-us/library/hh849812.aspx)
\n", - "[about_Execution_Policies](https://technet.microsoft.com/en-us/library/hh847748.aspx)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "For security reasons, PowerShell is set up by default to only allow signed scripts to execute. Executing the following\n", - "command will allow you to run unsigned scripts (you must run PowerShell as Administrator to do this).\n", - "```powershell\n", - "Set-ExecutionPolicy RemoteSigned\n", - "```" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Another way to run PowerShell scripts is to use Bypass as ExecutionPolicy:\n", - "```powershell\n", - "powershell.exe -ExecutionPolicy Bypass -File \"c:\\MyScript.ps1\"\n", - "```" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Or from within your existing PowerShell console or ISE session by running:\n", - "```powershell\n", - "Set-ExecutionPolicy Bypass Process\n", - "```" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "A temporary workaround for execution policy can also be achieved by running the PowerShell executable and\n", - "passing any valid policy as -ExecutionPolicy parameter. The policy is in effect only during process' lifetime, so no\n", - "administrative access to the registry is needed.\n", - "```powershell\n", - "C:\\>powershell -ExecutionPolicy RemoteSigned\n", - "```" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "There are multiple other policies available, and sites online often encourage you to use Set-ExecutionPolicy\n", - "Unrestricted. This policy stays in place until changed, and lowers the system security stance. This is not advisable.\n", - "Use of RemoteSigned is recommended because it allows locally stored and written code, and requires remotely\n", - "acquired code be signed with a certificate from a trusted root." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Also, beware that the Execution Policy may be enforced by Group Policy, so that even if the policy is changed to\n", - "Unrestricted system-wide, Group Policy may revert that setting at its next enforcement interval (typically 15\n", - "minutes). You can see the execution policy set at the various scopes using Get-ExecutionPolicy -List" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Aliases & Similar Functions" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "In PowerShell, there are many ways to achieve the same result. This can be illustrated nicely with the simple &\n", - "familiar Hello World example:\n", - "\n", - "```Powershell\n", - "Using Write-Host\n", - "```\n", - "Enter in the cell below: \n", - "```Powershell\n", - "Write-Host \"Hello World\"\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "It's worth noting that although Write-Output & Write-Host both write to the screen there is a subtle difference.\n", - "Write-Host writes only to stdout (i.e. the console screen), whereas Write-Output writes to both stdout AND to the\n", - "output [success] stream allowing for redirection. Redirection (and streams in general) allow for the output of one\n", - "command to be directed as input to another including assignment to a variable." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "```Powershell\n", - "Using Write-Host\n", - "```\n", - "Run the following command (Shift-Enter): \n", - "```Powershell\n", - "$message = Write-Host \"Hello World\"\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
Then call the message variable:\n", - "```Powershell\n", - "$message\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
You should have gotten nothing. Now lets try it again with Write-Output\n", - "```Powershell\n", - "$message = Write-Output \"Hello World\"\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
Then call the message variable again:\n", - "```Powershell\n", - "$message\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Explaination (Skip if your good) *** " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "## Run this if you want to see explaination of the top\n", - "Import-Module \"./modules/tutorial.psm1\"; embedYoutube -youtubeId \"QPMC0Q_4oug\" | Out-Display" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## The Pipeline - Using Output from a PowerShell" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Get-ChildItem | ForEach-Object {\n", - " Write-Host $_.LastWriteTime\n", - "}" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Get-ChildItem | Select-Object Name\n", - "#This may be shortened to:\n", - "gci | Select Name" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Get-ChildItem | ForEach-Object {\n", - " $_\n", - " #Copy-Item -Path $_.FullName -destination C:\\NewDirectory\\\n", - "}" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Note that the example above uses the \\\\$\\_ automatic variable\\. \\\\$\\_ is the short alias of $PSItem which is an automatic\n", - "variable which contains the current item in the pipeline\\." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This can be shortened to:\n", - "```powershell\n", - "gci | % { $_ }\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "## Run this if you want to see explaination of '1.3 The Pipeline'\n", - "Import-Module \"./modules/tutorial.psm1\"; embedYoutube -youtubeId \"qmCQYjvu6Gw\" | Out-Display" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Calling .Net Library Methods" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Static .Net library methods can be called from PowerShell by encapsulating the full class name in third bracket and\n", - "then calling the method using ::" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
Calling the method Path.GetFileName() by running the following command:\n", - "```Powershell\n", - "[System.IO.Path]::GetFileName('C:\\Windows\\explorer.exe')\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Static methods can be called from the class itself, but calling non-static methods requires an instance of the .Net\n", - "class (an object).\n", - "For example, the AddHours method cannot be called from the System.DateTime class itself. It requires an instance\n", - "of the class:" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Run the following command and see what happens\n", - "```powershell\n", - "[System.DateTime]::AddHours(15)\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "In this case, we first create an object, for example:\n", - "```Powershell\n", - "$Object = [System.DateTime]::Now\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now try to call upon the object variable you created and see if you can get the time" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Then, we can use methods of that object, even methods which cannot be called directly from the System.DateTime\n", - "class, like the AddHours method:\n", - "```Powershell\n", - "$Object.AddHours(15)\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Try to call again the object variable and what do you think happens ? " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "## Run this if you want to see explaination of '1.4 - Calling .Net Library Methods'\n", - "Import-Module \"./modules/tutorial.psm1\"; embedYoutube -youtubeId \"HVZ6jZGuJT0\" | Out-Display" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Installation or Setup" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Windows
\n", - "-- PowerShell is included with the Windows Management Framework. Installation and Setup are not required on modern versions of Windows.
\n", - "-- Updates to PowerShell can be accomplished by installing a newer version of the Windows Management Framework.\n", - "\n", - "Other Platforms
\n", - "-- PowerShell 6 can be installed on other platforms. The installation packages are available here.\n", - "-- For example, PowerShell 6, for Ubuntu 16.04, is published to package repositories for easy installation (and updates).\n", - "\n", - " To install run the following:" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Import the public repository GPG keys\n", - "```bash\n", - "curl https://packages.microsoft.com/keys/microsoft.asc | sudo apt-key add -\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Register the Microsoft Ubuntu repository\n", - "```bash\n", - "curl https://packages.microsoft.com/config/ubuntu/16.04/prod.list | sudo tee\n", - "/etc/apt/sources.list.d/microsoft.list\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Update apt-get\n", - "```bash\n", - "sudo apt-get update\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Install PowerShell\n", - "```bash\n", - "sudo apt-get install -y powershell\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Start PowerShell\n", - "```bash\n", - "powershell\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To update you just need to run\n", - "```bash\n", - "sudo apt-get upgrade powershell\n", - "```" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Commenting" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To comment on power scripts by prepending the line using the # (hash) symbol\n", - "```powershell\n", - "\n", - "# This is a comment in PowerShell\n", - "Get-ChildItem\n", - "```\n", - "\n", - "You can also have multi-line comments using <# and #> at the beginning and end of the comment respectively.\n", - "```powershell\n", - "<#\n", - "This is a multi-line\n", - "comment\n", - "#>\n", - "Get-ChildItem\n", - "```" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Creating Objects" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### The New-Object cmdlet is used to create an object." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Create a DateTime object and stores the object in variable \"\\$var\"\n", - "```powershell\n", - "$var = New-Object System.DateTime\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "calling constructor with parameters\n", - "```powershell\n", - "$sr = New-Object System.IO.StreamReader -ArgumentList \"file path\"\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### In many instances, a new object will be created in order to export data or pass it to another commandlet. \n", - "\n", - "This can be done like so:\n", - "```powershell\n", - "$newObject = New-Object -TypeName PSObject -Property @{\n", - "ComputerName = \"SERVER1\"\n", - "Role = \"Interface\"\n", - "Environment = \"Production\"\n", - "}\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### There are many ways of creating an object. \n", - "The following method is probably the shortest and fastest way to create a PSCustomObject:\n", - "```powershell\n", - "$newObject = [PSCustomObject]@{\n", - "ComputerName = 'SERVER1'\n", - "Role = 'Interface'\n", - "Environment = 'Production'\n", - "}\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### In case you already have an object, but you only need one or two extra properties.\n", - "Simply add that property by using Select-Object:\n", - "```powershell\n", - "Get-ChildItem | Select-Object FullName, Name,\n", - "@{Name='DateTime'; Expression={Get-Date}},\n", - "@{Name='PropertyName'; Expression={'CustomValue'}}\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "-- All objects can be stored in variables or passed into the pipeline. You could also add these objects to a collection and then show the results at the end.
\n", - "-- Collections of objects work well with Export-CSV (and Import-CSV). Each line of the CSV is an object, each column a property.
\n", - "-- Format commands convert objects into text stream for display. Avoid using Format-* commands until the final step of any data processing, to maintain the usability of the objects." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - " Explainer Video if you need it" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "## Run this if you want to see explaination of '1.4 - Calling .Net Library Methods'\n", - "Import-Module \"./modules/tutorial.psm1\"; embedYoutube -youtubeId \"6Q5_tjThrEo\" | Out-Display" - ] - } - ], - "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/1 - Tutorial with Videos/Chapter 02 - Variables in PowerShell.ipynb b/Notebooks/PowerShell/1 - Tutorial with Videos/Chapter 02 - Variables in PowerShell.ipynb deleted file mode 100755 index fa5ec2c..0000000 --- a/Notebooks/PowerShell/1 - Tutorial with Videos/Chapter 02 - Variables in PowerShell.ipynb +++ /dev/null @@ -1,592 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Chapter 2: Variables in PowerShell\n", - "\n", - "Variables are used for storing values. Let the value be of any type , we need to store it somewhere so that we can\n", - "use it throughout the console/script. Variable names in PowerShell begin with a \\\\$, as in \\\\$Variable1, and values are\n", - "assigned using =, like \\\\$Variable1 = \"Value 1\". PowerShell supports a huge number of variable types; such as text\n", - "strings, integers, decimals, arrays, and even advanced types like version numbers or IP addresses." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 2.1 Simple variable" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "All variables in PowerShell begin with a US dollar sign \\$

\n", - "The following statement allocates a variable called foo with a string value of \"bar\".\n", - "\n", - "```powershell\n", - "$foo = \"bar\"\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "bar\n" - ] - } - ], - "source": [ - "$foo = \"bar\"\n", - "\n", - "$foo" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 2.2 Arrays" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Array declaration in Powershell is almost the same as instantiating any other variable, i.e. you use a \\\\$name = syntax\\.\n", - "The items in the array are declared by separating them by commas(\\,)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 2.2.1 Array of Integers and Array of Strings" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Enter the following and then call your variable to see the result\n", - "```powershell\n", - "$myArrayOfInts = 1,2,3,4\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Enter the following and then call your variable to see the result\n", - "```powershell\n", - "$myArrayOfStrings = \"1\",\"2\",\"3\",\"4\"\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 2.2.2 - Adding to an array" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Adding to an array is as simple as using the + operator:\n", - "\n", - "$myArrayOfInts = $myArrayOfInts + 5\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now call on the $myArrayOfInts and review the results\n", - "\n", - " result should now contains 1,2,3,4 & 5!\n", - "\n", - "```powershell\n", - "$myArrayOfInts\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 2.2.3 - Combining arrays together" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Build the first array:\n", - "```powershell\n", - "$firstArray = 1,2,3,4\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Build the second array:\n", - "```powershell\n", - "$secondArray = 5,6,7,8\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now lets combine them!\n", - "```\n", - "$combinedArray = $firstArray + $secondArray\n", - "```" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - " Explanation Video if you want it" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "## Run this if you want to see explaination of the top\n", - "Import-Module \"./modules/tutorial.psm1\"; embedYoutube -youtubeId \"1oqnVJuI4uM\" | Out-Display" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 2.3 List Assignment of Multiple Variables" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Powershell allows multiple assignment of variables and treats almost everything like an array or list. This means that instead of doing something like this\n", - "Run the following command:
\n", - "\n", - "\\\\$input = \"foo.bar.baz\"
\n", - "\\\\$parts = \\\\$input.Split(\".\")
\n", - "\\\\$foo = \\\\$parts[0]
\n", - "\\\\$bar = \\\\$parts[1]
\n", - "\\\\$baz = \\\\$parts[2]
" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "You can simply do this:
\n", - "\\\\$foo, \\\\$bar, \\\\$baz = \\\\$input.Split(\".\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Since Powershell treats assignments in this manner like lists, if there are more values in the list than items in your\n", - "list of variables to assign them to, the last variable becomes an array of the remaining values. \n", - "This means you can also do things like this:\n", - "```\n", - "$input = \"foo.bar.baz\"\n", - "$foo, $leftover = $input.Split(\".\") #Sets $foo = \"foo\", $leftover = [\"bar\",\"baz\"]\n", - "$bar = $leftover[0] # $bar = \"bar\"\n", - "$baz = $leftover[1] # $baz = \"baz\"\n", - "```" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - " Explainer Video if you want" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "## Run this if you want to see explaination of the top\n", - "Import-Module \"./modules/tutorial.psm1\"; embedYoutube -youtubeId \"LjVPJeQ1IFA\" | Out-Display" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 2.4: Scope" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The default scope for a variable is the enclosing container. If outside a script, or other container then the scope is\n", - "Global. \n", - "To specify a scope, it is prefixed to the variable name \n", - "```powershell\n", - "$scope:varname\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "$foo = \"Global Scope\"\n", - "\n", - "function myFunc {\n", - " $foo = \"Function (local) scope\"\n", - " Write-Host $global:foo\n", - " Write-Host $local:foo\n", - " Write-Host $foo\n", - "}\n", - "\n", - "myFunc\n", - "Write-Host $local:foo\n", - "Write-Host $foo" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "\r\n", - "
\r\n", - " \r\n", - " \r\n", - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "\n", - "

via GIPHY

" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "#Its like inception. Here is an example\n", - "#!html\n", - "

via GIPHY

" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "yellow\n", - "red\n", - "green\n", - "blue\n" - ] - } - ], - "source": [ - "#dream within a dream\n", - "function dreamOne {\n", - " $henry = \"yellow\"\n", - " function dreamTwo {\n", - " $sam = \"green\"\n", - " function dreamThree {\n", - " $sally = \"red\"\n", - " function dreamFour {\n", - " $bob = \"blue\"\n", - " \n", - " Write-Host $henry\n", - " Write-Host $sally\n", - " Write-Host $sam\n", - " Write-Host $bob\n", - " }\n", - " dreamFour\n", - " }\n", - " dreamThree\n", - " }\n", - " dreamTwo\n", - "}\n", - "\n", - "dreamOne" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "## Run this if you want to see explaination of the top\n", - "Import-Module \"./modules/tutorial.psm1\"; embedYoutube -youtubeId \"PGL_1UJPNqI\" | Out-Display" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 2.5 Removing a variable" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To remove a variable from memory, one can use the Remove-Item cmdlet. Note: The variable name does NOT\n", - "include the $.\n", - "```powershell\n", - "Remove-Item Variable:\\foo\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "$var = \"Some Variable\" #Define variable 'var' containing the string 'Some Variable'\n", - "$var #For test and show string 'Some Variable' on the console" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Remove-Variable -Name var\n", - "$var" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "#also can use alias 'rv'\n", - "rv $var" - ] - } - ], - "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": false, - "toc-showcode": false, - "toc-showmarkdowntxt": true, - "toc-showtags": false - }, - "nbformat": 4, - "nbformat_minor": 4 -} diff --git a/Notebooks/PowerShell/1 - Tutorial with Videos/Chapter 03 - Operators.ipynb b/Notebooks/PowerShell/1 - Tutorial with Videos/Chapter 03 - Operators.ipynb deleted file mode 100755 index 8ea4282..0000000 --- a/Notebooks/PowerShell/1 - Tutorial with Videos/Chapter 03 - Operators.ipynb +++ /dev/null @@ -1,577 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Chapter 3: Operators\n", - "- This tutorial was sourced from the great work done by http://GoalKicker.com/PowerShellBook and the content is written by the beautiful people at Stack Overflow.\n", - "\n", - "Table of Contents
\n", - "1. [Comparison Operators](#1)\n", - "2. [Arithmetic Operators](#2)\n", - "3. [Assignment Operators](#3)\n", - "4. [Redirection Operators](#4)\n", - "5. [Mixing operand types, the types of the left operand dictatees the behavior](#5)\n", - "6. [Logical Operators](#6)\n", - "7. [String Manipulation Operators](#7)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 3.1: Comparison Operators" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "PowerShell comparison operators are comprised of a leading dash (-) followed by a name (eq for equal, gt for\n", - "greater than, etc...).
\n", - "Names can be preceded by special characters to modify the behavior of the operator:\n", - "```powershell\n", - "i # Case-Insensitive Explicit (-ieq)\n", - "c # Case-Sensitive Explicit (-ceq)\n", - "```\n", - "Case-Insensitive is the default if not specified, (\"a\" -eq \"A\") same as (\"a\" -ieq \"A\")." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Simple comparison operators (Run commands below)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "2 -eq 2 # Equal to (==)\n", - "2 -ne 4 # Not equal to (!=)\n", - "5 -gt 2 # Greater-than (>)\n", - "5 -ge 5 # Greater-than or equal to (>=)\n", - "5 -lt 10 # Less-than (<)\n", - "5 -le 5 # Less-than or equal to (<=)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "String comparison operators:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "\"MyString\" -like \"String*\" # Match using the wildcard character (*)\n", - "\"MyString\" -notlike \"Other*\" # Does not match using the wildcard character (*)\n", - "\"MyString\" -match '^String$' # Matches a string using regular expressions\n", - "\"MyString\" -notmatch '^Other$' # Does not match a string using regular expressions" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Connection comparison operators:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "\"abc\", \"def\",\"blah\" -contains \"blah\" # Returns true when the value (right) is present\n", - " # in the array (left)\n", - "\"abc\", \"def\" -notcontains \"123\" # Returns true when the value (right) is not present\n", - " # in the array (left)\n", - "\"def\" -in \"abc\", \"def\" # Returns true when the value (left) is present\n", - " # in the array (right)\n", - "\"123\" -notin \"abc\", \"def\" # Returns true when the value (left) is not present\n", - " # in the array (right)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "\"poodle\" -in @('chihuahua','german shepard','poodle','husky')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - " If you need explanation of operators" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "## Run this if you want to see explaination of the top\n", - "Import-Module \"./modules/tutorial.psm1\"; embedYoutube -youtubeId \"2Guf7fCGrmo\" | Out-Display" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 3.2: Arithmetic Operators" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "1 + 2 # Addition\n", - "1 - 2 # Subtraction\n", - "-1 # Set negative value\n", - "1 * 2 # Multiplication\n", - "1 / 2 # Division\n", - "10 % 3 # Modulus\n", - "32 -shl 2 # Bitwise Shift-left\n", - "32 -shr 1 # Bitwise Shift-right" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 3.2.1: Shifting Example using Subnets" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# /24 - 255 host addresses \n", - "$shift = 3\n", - "\n", - "$hostIPs = 256 -shr $shift\n", - "$networks = 256 / $hostIPs\n", - "$subnetMask = 24 + $shift\n", - "\n", - "Write-Host \"The total number of networks are: \", $networks\n", - "Write-Host \"The total number of host addresses are: \", $hostIPs\n", - "Write-Host \"Subnet Mask is /$subnetMask or 255.255.255.$(256-$hostIPs)\"" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 3.3: Assignment Operators" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Simple Arithmetic:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "$var = $var - 2\n", - "$var -= 2" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "$var = 1; $var # Assignment. Sets the value of a variable to the specified value\n", - "$var += 2; $var # Addition. Increases the value of a variable by the specified value\n", - "$var -= 1; $var # Subtraction. Decreases the value of a variable by the specified value\n", - "$var *= 2; $var # Multiplication. Multiplies the value of a variable by the specified value\n", - "$var /= 2; $var # Division. Divides the value of a variable by the specified value\n", - "$var %= 2; $var# Modulus. Divides the value of a variable by the specified value and then assigns the remainder (modulus) to the variabl" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "$var" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Increment and decrement:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "$var = 5;\n", - "$var++; $var # Increases the value of a variable, assignable property, or array element by 1\n", - "$var--; $var # Decreases the value of a variable, assignable property, or array element by 1" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 3.4: Redirection Operators" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Success output stream:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Success output stream:\n", - "cmdlet > file # Send success output to file, overwriting existing content\n", - "cmdlet >> file # Send success output to file, appending to existing content\n", - "cmdlet 1>&2 # Send success and error output to error stream\n", - "Error output stream:\n", - "cmdlet 2> file # Send error output to file, overwriting existing content\n", - "cmdlet 2>> file # Send error output to file, appending to existing content\n", - "cmdlet 2>&1 # Send success and error output to success output stream\n", - "Warning output stream: (PowerShell 3.0+)\n", - "cmdlet 3> file # Send warning output to file, overwriting existing content\n", - "cmdlet 3>> file # Send warning output to file, appending to existing content\n", - "cmdlet 3>&1 # Send success and warning output to success output stream\n", - "Verbose output stream: (PowerShell 3.0+)\n", - "cmdlet 4> file # Send verbose output to file, overwriting existing content\n", - "cmdlet 4>> file # Send verbose output to file, appending to existing content\n", - "cmdlet 4>&1 # Send success and verbose output to success output stream\n", - "Debug output stream: (PowerShell 3.0+)\n", - "cmdlet 5> file # Send debug output to file, overwriting existing content\n", - "cmdlet 5>> file # Send debug output to file, appending to existing content\n", - "cmdlet 5>&1 # Send success and debug output to success output stream\n", - "Information output stream: (PowerShell 5.0+)\n", - "cmdlet 6> file # Send information output to file, overwriting existing content\n", - "cmdlet 6>> file # Send information output to file, appending to existing content\n", - "cmdlet 6>&1 # Send success and information output to success output stream\n", - "All output streams:\n", - "cmdlet *> file # Send all output streams to file, overwriting existing content\n", - "cmdlet *>> file # Send all output streams to file, appending to existing content\n", - "cmdlet *>&1 # Send all output streams to success output stream\n", - "Differences to the pipe operator (|)\n", - "Redirection operators only redirect streams to files or streams to streams. The pipe operator pumps an object\n", - "down the pipeline to a cmdlet or the output. How the pipeline works differs in general from how redirection works\n", - "and can be read on Working with the PowerShell pipeline" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - " Example" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Write-Output \"Test\" > Chapter3_TestFile # Send success output to file, overwriting existing content\n", - "Write-Output \"Test Append\" >> Chapter3_TestFile # Send success output to file, overwriting existing content\n", - "dir 'C:\\', 'fakepath' 2>&1 >> Chapter3_TestFile\n", - "Get-Content Chapter3_TestFile" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 3.5: Mixing operand types, the type of the left operand dictates the behavior" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "For Addition" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "\"4\" + 2 # Gives \"42\"\n", - "4 + \"2\" # Gives 6" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "1,2,3 + \"Hello\" # Gives 1,2,3,\"Hello\"" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "\"Hello \" + 1,2,3 # Gives \"Hello1 2 3\"" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "For Multiplication" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "\"3\" * 10 # Gives \"33\"" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "2 * \"34\" # Gives 6" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "1,2,3 * 2 # Gives 1,2,3,1,2,3" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "2 * 1,2,3 # Gives an error op_Multiply is missing" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The impact may have hidden consequences on comparison operators:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "$a = Read-Host \"Enter a number\" ## Enter 33\n", - "$a -gt 5" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "5 -lt $a ## But go the other way" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 3.6: Logical Operators" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "-and # Logical and\n", - "-or # Logical or\n", - "-xor # Logical exclusive or\n", - "-not # Logical not\n", - "! # Logical not" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 3.7: String Manipulation Operators" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Replace operator:\n", - "The -replace operator replaces a pattern in an input value using a regular expression. This operator uses two\n", - "arguments (separated by a comma): a regular expression pattern and its replacement value (which is optional and\n", - "an empty string by default)." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "\"Seattle is beautiful. The rain in Seattle\" -replace 'Seattle','Miami' #Returns: The hail in Seattle" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "\"kenmyer@contoso.com\" -replace '^[\\w]+@(.+)', '$1' #Returns: contoso.com" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Split and Join operators:\n", - "The -split operator splits a string into an array of sub-strings." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "$whatever = \"A B C\" -split \" \" #Returns an array string collection object containing A,B and C." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "$whatever[0]" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The -join operator joins an array of strings into a single string." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "$test = \"E\",\"F\",\"G\" -join \":\" #Returns a single string: E:F:G" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "$test" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "$test -split \":\"" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "## Run this if you want to see explaination of the top\n", - "Import-Module \"./modules/tutorial.psm1\"; embedYoutube -youtubeId \"GCwJIhrC8zc\" | Out-Display" - ] - }, - { - "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": false - }, - "nbformat": 4, - "nbformat_minor": 4 -} diff --git a/Notebooks/PowerShell/1 - Tutorial with Videos/Chapter 04 - Special Operators.ipynb b/Notebooks/PowerShell/1 - Tutorial with Videos/Chapter 04 - Special Operators.ipynb deleted file mode 100755 index f223e24..0000000 --- a/Notebooks/PowerShell/1 - Tutorial with Videos/Chapter 04 - Special Operators.ipynb +++ /dev/null @@ -1,153 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Chapter 4: Special Operators\n", - "- This tutorial was sourced from the great work done by http://GoalKicker.com/PowerShellBook and the content is written by the beautiful people at Stack Overflow.\n", - "\n", - "Table of Contents
\n", - "1. [Array Expression Operator](#1)\n", - "2. [Call Operation](#2)\n", - "3. [Dot Sourcing Operator](#3)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 4.1: Array Expression Operator" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Returns the expression as an array.\n", - "```powershell\n", - "@(Get-ChildItem $env:windir\\System32\\ntdll.dll)\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "@(Get-ChildItem \"./Chapter 4 - Special Operators.ipynb\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Will return an array with one item\n", - "```powershell\n", - "@(Get-ChildItem $env:windir\\System32)\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "@(Get-ChildItem \"./\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Will return an array with all the items in the folder (which is not a change of behavior from the inner expression." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 4.2: Call Operation\n", - "```powershell\n", - "# Powershell script $$\n", - "$no = \"blah\"\n", - "$stuff = \"blah\"\n", - "Will execute Get-ChildItem\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "$command = 'Get-ChildItem'\n", - "& $command" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Invoke-Command -ScriptBlock {Write-Host \"Hello World\"}" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 4.3: Dot Sourcing Operator" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "```powershell\n", - ". .\\modules\\myScript.ps1\n", - "```\n", - "When you use a period followed by the script path, it runs ```.\\myScript.ps1``` in the current scope making any functions, and variable available in the current scope." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - ". .\\modules\\myScript.ps1" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "## Run this if you want to see explaination of the top\n", - "Import-Module \"./modules/tutorial.psm1\"; embedYoutube -youtubeId \"8TrlKV-HZXY\" | Out-Display" - ] - } - ], - "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/1 - Tutorial with Videos/Chapter 05 - Basic Set Operation.ipynb b/Notebooks/PowerShell/1 - Tutorial with Videos/Chapter 05 - Basic Set Operation.ipynb deleted file mode 100755 index 775895c..0000000 --- a/Notebooks/PowerShell/1 - Tutorial with Videos/Chapter 05 - Basic Set Operation.ipynb +++ /dev/null @@ -1,342 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Chapter 5: Basic Set Operation\n", - "- This tutorial was sourced from the great work done by http://GoalKicker.com/PowerShellBook and the content is written by the beautiful people at Stack Overflow.\n", - "\n", - "Table of Contents
\n", - "1. [Filtering: Where-Object / where /](#1)\n", - "2. [Ordering: Sort-Object / sort](#2)\n", - "3. [Grouping: Group-Object /group](#3)\n", - "3. [Projecting: Select-Object / select](#4)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 5.1: Filtering: Where-Object /where / ?\n", - "Filter an enumeration by using a conditional expression\n", - "```powershell\n", - "Where-Object\n", - "where\n", - "?\n", - "```" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Example:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "$names = @( \"Aaron\", \"Albert\", \"Alphonse\",\"Bernie\", \"Charlie\", \"Danny\", \"Ernie\", \"Frank\")\n", - "$names" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "$names.count" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "$names | Where-Object { $_ -like \"A*\" }" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "$names | where { $_ -like \"A*\" }" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "$names | ? { $_ -like \"A*\" }" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 5.2: Ordering: Sort-Object /sort" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Sort an enumeration in either ascending or descending order
\n", - "Synonyms:\n", - "```powershell\n", - "Sort-Object\n", - "sort\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "## Create array\n", - "$names = @( \"Aaron\", \"Aaron\", \"Bernie\", \"Charlie\", \"Danny\" )" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Sort by ascending order (default)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "## Sort array in ascending order (default)\n", - "$names | Sort-Object" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "## Shorter command\n", - "$names | sort" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Sort by descending order" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "$names | Sort-Object -Descending" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "$names | sort -Descending" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Sort by using an expression" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "## Sort list by character length which again defaults in ascending order.\n", - "$names | Sort-Object { $_.length }" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 5.3: Grouping: Group-Object /group" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "You can group an enumeration based on an expression.
Synonyms:\n", - "```powershell\n", - "Group-Object\n", - "group\n", - "```" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Create array" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "$names = @( \"Aaron\", \"Albert\", \"Alphonse\",\"Bernie\", \"Charlie\", \"Danny\", \"Ernie\", \"Frank\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "group objects by length of characters in name" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "$names | Group-Object -Property Length" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "shorter alias command to group. Does the same thing. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "$names | group -Property Length" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 5.4: Projecting: Select-Object / select" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Projecting an enumeration allows you to extract specific members of each object, to extract all the details, or to compute values for each object

Synonyms:\n", - "```powershell\n", - "Select-Object\n", - "SELECT\n", - "```" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Selecting a subset of the properties:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# Gets the current directory and specify only to return the columns Name, FullName Attributes.\n", - "$dir = dir \"./\"\n", - "$dir | Select-Object Name, FullName, Attributes" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Shorter alias command that does the same thing" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "$dir | select Name, FullName, Attributes" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Selecting the first element, and show all its properties:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "$dir | select -first 1 *" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "## Run this if you want to see explaination of the top\n", - "Import-Module \"./modules/tutorial.psm1\"; embedYoutube -youtubeId \"v4P69rbolfo\" | Out-Display" - ] - } - ], - "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/1 - Tutorial with Videos/Chapter 06 - Conditional Logic.ipynb b/Notebooks/PowerShell/1 - Tutorial with Videos/Chapter 06 - Conditional Logic.ipynb deleted file mode 100755 index 015330b..0000000 --- a/Notebooks/PowerShell/1 - Tutorial with Videos/Chapter 06 - Conditional Logic.ipynb +++ /dev/null @@ -1,370 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Conditional Logic" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 6.1: If, Else, and Else If\n", - "\n", - "Powershell supports standard conditional logic operators, much like many programming languages. These allow\n", - "certain functions or commands to be run under particular circumstances.\n", - "\n", - "Note the above use -eq(equality) CmdLet and not = or == as many other languages do for equality" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "With an if the commands inside the brackets ({}) are only executed if the conditions inside the if(()) are met" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "$test = \"test\"\n", - "if ($test -eq \"test\"){\n", - " Write-Host \"if condition met this message will display\"\n", - "}" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "You can also do an else. Here the else commands are executed if the if conditions are not met:" - ] - }, - { - "cell_type": "code", - "execution_count": 31, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "if condition not met this will display\n" - ] - } - ], - "source": [ - "$test = \"test\"\n", - "if ($test -eq \"test2\"){\n", - " Write-Host \"if condition met this will display\"\n", - "}\n", - "else{\n", - " Write-Host \"if condition not met this will display\"\n", - "}" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "or an elseif. An else if runs the commands if the if conditions are not met and the elseif conditions are met:" - ] - }, - { - "cell_type": "code", - "execution_count": 34, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "default backup condition statement\n" - ] - } - ], - "source": [ - "$test = \"test\"\n", - "if ($test -eq \"test2\"){\n", - " Write-Host \"if condition met\"\n", - "}\n", - "elseif ($test -eq \"test3\"){\n", - " Write-Host \"ifelse condition met\"\n", - "} else {\n", - " Write-Host \"default backup condition statement\"\n", - "}" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 6.2: Negation" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "You may want to negate a boolean value, i.e. enter an if statement when a condition is false rather than true. This\n", - "can be done by using the -Not CmdLet" - ] - }, - { - "cell_type": "code", - "execution_count": 37, - "metadata": {}, - "outputs": [], - "source": [ - "$test = \"test\"\n", - "if (-Not ($test -ne \"test\") ) {\n", - " Write-Host \"if condition not met\"\n", - "}" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "You can also use !:" - ] - }, - { - "cell_type": "code", - "execution_count": 38, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "if condition not met\n" - ] - } - ], - "source": [ - "$test = \"test\"\n", - "if (!($test -eq \"test2\")){\n", - " Write-Host \"if condition not met\"\n", - "}" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "there is also the -ne (not equal) operator:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "$test = \"test\"\n", - "if ($test -ne \"test2\"){\n", - " Write-Host \"variable test is not equal to 'test2'\"\n", - "}" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 6.3: Negation\n", - "\n", - "If you want to use the shorthand you can make use of conditional logic with the following shorthand. Only the\n", - "string 'false' will evaluate to true (2.0)." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - " Configure Variables" - ] - }, - { - "cell_type": "code", - "execution_count": 53, - "metadata": {}, - "outputs": [], - "source": [ - "#Done in Powershell 2.0\n", - "$boolean = $false;\n", - "$string = \"false\";\n", - "$emptyString = \"\";" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "this does not run because $boolean is false" - ] - }, - { - "cell_type": "code", - "execution_count": 42, - "metadata": {}, - "outputs": [], - "source": [ - "$blah = $false\n", - "If($blah){\n", - " Write-Host \"Shorthand If conditions can be nice, just make sure they are always boolean.\"\n", - "}" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This does run because the string is non-zero length" - ] - }, - { - "cell_type": "code", - "execution_count": 51, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "If the variable is not strictly null or Boolean false, it will evaluate to true as it is an object or string with length greater than 0.\n", - "5\n" - ] - } - ], - "source": [ - "$string = \"false\"\n", - "If($string){\n", - " Write-Host \"If the variable is not strictly null or Boolean false, it will evaluate to true as it is an object or string with length greater than 0.\"\n", - "}\n", - "$string.length" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This does not run because the string is zero-length" - ] - }, - { - "cell_type": "code", - "execution_count": 55, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "0\n" - ] - } - ], - "source": [ - "$emptyString=\"\"\n", - "If($emptyString){\n", - " Write-Host \"Checking empty strings can be useful as well.\"\n", - "}\n", - "$emptyString.length" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This does not run because the condition is null" - ] - }, - { - "cell_type": "code", - "execution_count": 58, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Checking Nulls will not print this statement.\n" - ] - } - ], - "source": [ - "$null\n", - "If(!$null){\n", - " Write-Host \"Checking Nulls will not print this statement.\"\n", - "}" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - " Explainer video if you want" - ] - }, - { - "cell_type": "code", - "execution_count": 59, - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - " " - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "## Run this if you want to see explaination of the top\n", - "Import-Module \"./modules/tutorial.psm1\"; embedYoutube -youtubeId \"LBqD4sCgl-w\" | Out-Display" - ] - }, - { - "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/1 - Tutorial with Videos/Chapter 07 - Loops.ipynb b/Notebooks/PowerShell/1 - Tutorial with Videos/Chapter 07 - Loops.ipynb deleted file mode 100755 index 0201d1d..0000000 --- a/Notebooks/PowerShell/1 - Tutorial with Videos/Chapter 07 - Loops.ipynb +++ /dev/null @@ -1,602 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Chapter 7: Loops\n", - "\n", - "- This tutorial was sourced from the great work done by http://GoalKicker.com/PowerShellBook and the content is written by the beautiful people at Stack Overflow.\n", - "\n", - "Table of Contents
\n", - "1. [Foreach](#1)\n", - "2. [For](#2)\n", - "3. [ForEach() Method](#3)\n", - "4. [ForEach-Object](#4)\n", - "5. [Continue](#5)\n", - "6. [Break](#6)\n", - "7. [Simple Switch with Break](#7)\n", - "8. [While](#8)\n", - "9. [Do](#9)\n", - "\n", - "A loop is a sequence of instruction(s) that is continually repeated until a certain condition is reached. Being able to\n", - "have your program repeatedly execute a block of code is one of the most basic but useful tasks in programming. A\n", - "loop lets you write a very simple statement to produce a significantly greater result simply by repetition. If the\n", - "condition has been reached, the next instruction \"falls through\" to the next sequential instruction or branches\n", - "outside the loop." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 7.1: Foreach" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "ForEach has two different meanings in PowerShell. One is a keyword and the other is an alias for the ForEachObject cmdlet. The former is described here.\n", - "This example demonstrates printing all items in an array to the console host:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "$Names = @('Amy', 'Bob', 'Celine', 'David')\n", - "ForEach ($Name in $Names)\n", - "{\n", - " Write-Host \"Hi, my name is $Name! My name character length is $($name.length)\"\n", - "}" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This example demonstrates capturing the output of a ForEach loop:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "$Numbers = ForEach ($Number in (1..20) ) {\n", - " Write-host $Number\n", - " #$Number # Alternatively, Write-Output $Number\n", - "}" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Like the last example, this example, instead, demonstrates creating an array prior to storing the loop:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "$Number = 0\n", - "$Numbers = @()\n", - "Write-Host \"Value of array prior to loop is $Number\"\n", - "ForEach ($Number in 1..20)\n", - "{\n", - " $Numbers += $Number\n", - " $Number\n", - "}\n", - "Write-Host \"The value of the array after the loop is $Number\"" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 7.2: For\n", - "\n", - "A typical use of the for loop is to operate on a subset of the values in an array. In most cases, if you want to iterate\n", - "all values in an array, consider using a foreach statement." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "for($i = 0; $i -le 5; $i++){\n", - " \"$i\"\n", - "}" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Section 7.3: ForEach() Method" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#Version > 4.0\n", - "Instead of the ForEach-Object cmdlet, the here is also the possibility to use a ForEach method directly on object\n", - "arrays like so." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "(1..10).ForEach(\n", - " {\n", - " Write-Host \"$_ : $_ * $_ = $($_*$_)\"\n", - " #$_ * $_\n", - " }\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "or - if desired - the parentheses around the script block can be omitted.\n", - "
Both will have the same output" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "(1..10).ForEach{\n", - " Write-Host \"$_ : $_ * $_ = $($_*$_)\"\n", - "}" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Section 7.4: ForEach-Object" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The ForEach-Object cmdlet works similarly to the foreach statement, but takes its input from the pipeline." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Basic usage" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "$object | ForEach-Object {\n", - " code_block\n", - "}" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "(1..10) | ForEach-Object {\n", - " Write-Host \"$_ : $_ * $_ = $($_*$_)\"\n", - "}" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Example:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "$names = @(\"Any\",\"Bob\",\"Celine\",\"David\")\n", - "$names | ForEach-Object {\n", - " \"Hi, my name is $_!\"\n", - "}" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Foreach-Object has two default aliases, foreach and % (shorthand syntax). Most common is % because foreach can\n", - "be confused with the foreach statement. " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Examples:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "$names | % {\n", - " \"Hi, my name is $_!\"\n", - "}\n", - "$names | foreach {\n", - " \"Hi, my name is $_!\"\n", - "}" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Advanced usage" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Foreach-Object stands out from the alternative foreach solutions because it's a cmdlet which means it's designed\n", - "to use the pipeline. Because of this, it has support for three scriptblocks just like a cmdlet or advanced function:" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Begin: Executed once before looping through the items that arrive from the pipeline. Usually used to create\n", - "functions for use in the loop, creating variables, opening connections (database, web +) etc.
\n", - "Process: Executed once per item arrived from the pipeline. \"Normal\" foreach codeblock. This is the default\n", - "used in the examples above when the parameter isn't specified.
\n", - "End: Executed once after processing all items. Usually used to close connections, generate a report etc." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Example:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "\"Any\",\"Bob\",\"Celine\",\"David\" | ForEach-Object -Begin {\n", - " Write-Host \"Beginning statement\"\n", - " $results = @()\n", - "} -Process {\n", - " Write-Host \"Creating and storing message\"\n", - " #Create and store message\n", - " $results += \"Hi, my name is $_!\"\n", - "} -End {\n", - " #Count messages and output\n", - " Write-Host \"Total messages: $($results.Count)\"\n", - " $results\n", - "}" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Section 7.5: Continue" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The Continue operator works in For, ForEach, While and Do loops. It skips the current iteration of the loop, jumping\n", - "to the top of the innermost loop." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "$i =0\n", - "while ($i -lt 20) {\n", - " $i++\n", - " if ($i -eq 7) { continue }\n", - " Write-Host $I\n", - "}\n", - "#The above will output 1 to 20 to the console but miss out the number 7.\n", - "#Note: When using a pipeline loop you should use return instead of Continue." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 7.6: Break\n", - "\n", - "The break operator will exit a program loop immediately. It can be used in For, ForEach, While and Do loops or in a\n", - "Switch Statement." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "$i = 0\n", - "while ($i -lt 15) {\n", - " $i++\n", - " if ($i -eq 7) {break}\n", - " Write-Host $i\n", - "}" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The above will count to 15 but stop as soon as 7 is reached.\n", - "Note: When using a pipeline loop, break will behave as continue. To simulate break in the pipeline loop you need\n", - "to incorporate some additional logic, cmdlet, etc. It is easier to stick with non-pipeline loops if you need to use\n", - "break." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Break Labels
\n", - "\n", - " Break can also call a label that was placed in front of the instantiation of a loop:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "$i = 0\n", - ":mainLoop While ($i -lt 15) {\n", - " Write-Host $i -ForegroundColor 'Cyan'\n", - " $j = 0\n", - " While ($j -lt 15) {\n", - " Write-Host $j -ForegroundColor 'Magenta'\n", - " $k = $i*$j\n", - " Write-Host $k -ForegroundColor 'Green'\n", - " if ($k -gt 100) {\n", - " break mainLoop\n", - " }\n", - " $j++\n", - " }\n", - " $i++\n", - "}" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Note: This code will increment \\\\$i to 8 and \\\\$j to 13 which will cause \\\\$k to equal 104. Since \\\\$ exceed 100, the code\n", - "will then break out of both loops." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Section 7.7: While" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "A while loop will evaluate a condition and if true will perform an action. As long as the condition evaluates to true\n", - "the action will continue to be performed." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "while(condition){\n", - " code_block\n", - "}" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "$i = 10\n", - "while($i -ge 0){\n", - " $i\n", - " $i--\n", - "}" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Unlike the Do-While loop the condition is evaluated prior to the action's first execution. The action will not be\n", - "performed if the initial condition evaluates to false.\n", - "Note: When evaluating the condition, PowerShell will treat the existence of a return object as true. This can be used\n", - "in several ways but below is an example to monitor for a process. This example will spawn a notepad process and\n", - "then sleep the current shell as long as that process is running. When you manually close the notepad instance the\n", - "while condition will fail and the loop will break." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Start-Process notepad.exe\n", - "while(Get-Process notepad -ErrorAction SilentlyContinue){\n", - " Start-Sleep -Milliseconds 500\n", - "}" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Section 7.8: Do" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Do-loops are useful when you always want to run a codeblock at least once. A Do-loop will evaluate the condition\n", - "after executing the codeblock, unlike a while-loop which does it before executing the codeblock.\n", - "You can use do-loops in two ways:" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - " Loop while the condition is true:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Do {\n", - " code_block\n", - "} while (condition)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Loop until the condition is true, in other words, loop while the condition is false:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Do {\n", - " code_block\n", - "} until (condition)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Real Examples:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "$i = 0\n", - "Do {\n", - " $i++\n", - " \"Number $i\"\n", - "} while ($i -ne 3)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "$i = 0\n", - "Do {\n", - " $i++\n", - " \"Number $i\"\n", - "} until ($i -eq 3)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Do-While and Do-Until are antonymous loops. If the code inside the same, the condition will be reversed. The\n", - "example above illustrates this behaviour." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "## Run this if you want to see explaination of the top\n", - "Import-Module \"./modules/tutorial.psm1\"; embedYoutube -youtubeId \"_WIZPgPB8Wk\" | Out-Display" - ] - } - ], - "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/1 - Tutorial with Videos/Chapter 08 - Switch Statement.ipynb b/Notebooks/PowerShell/1 - Tutorial with Videos/Chapter 08 - Switch Statement.ipynb deleted file mode 100755 index dc75581..0000000 --- a/Notebooks/PowerShell/1 - Tutorial with Videos/Chapter 08 - Switch Statement.ipynb +++ /dev/null @@ -1,771 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Chapter 8: Switch statement" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "- This tutorial was sourced from the great work done by http://GoalKicker.com/PowerShellBook and the content is written by the beautiful people at Stack Overflow.\n", - "\n", - "Table of Contents
\n", - "1. [Simple Switch](#1)\n", - "2. [Switch Statement with CaseSensitive Parameter](#2)\n", - "3. [Switch Statement with Wildcard Parameter](#3)\n", - "4. [Switch Statement with File Parameter](#4)\n", - "5. [Simple Switch with Default Condition](#5)\n", - "6. [Switch Statement with Regex Parameter](#6)\n", - "7. [Simple Switch with Break](#7)\n", - "8. [Switch Statement with Exact Parameter](#8)\n", - "9. [Switch Statement with Expressions](#9)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "A switch statement allows a variable to be tested for equality against a list of values. Each value is called a case, and\n", - "the variable being switched on is checked for each switch case. It enables you to write a script that can choose from\n", - "a series of options, but without requiring you to write a long series of if statements." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 8.1: Simple Switch\n", - "\n", - "Switch statements compare a single test value to multiple conditions, and performs any associated actions for\n", - "successful comparisons. It can result in multiple matches/actions." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Given the following switch...\n", - "```powershell\n", - "switch($myValue)\n", - "{\n", - " 'First Condition' { 'First Action' }\n", - " 'Second Condition' { 'Second Action' }\n", - "}\n", - "```\n", - "\n", - "First Action will be output if \\\\$myValue is set as 'First Condition'.
\n", - "Section Action will be output if \\\\$myValue is set as 'Second Condition'.\n", - "\n", - "Nothing will be output if $myValue does not match either conditions." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Example" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "$myValue = \"punch\"\n", - "\n", - "switch($myValue)\n", - "{\n", - " 'punch' { 'I punched you for 50 damage' }\n", - " 'kick' { 'I kicked you for 50 damage' }\n", - "}" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Section 8.2: Switch Statement with CaseSensitive Parameter\n", - "\n", - "The -CaseSensitive parameter enforces switch statements to perform exact, case-sensitive matching against\n", - "conditions." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Example:\n", - "```powershell\n", - "switch -CaseSensitive ('Condition')\n", - "{\n", - " 'condition' {'First Action'}\n", - " 'Condition' {'Second Action'}\n", - " 'conditioN' {'Third Action'}\n", - "}\n", - "```\n", - "\n", - "Second Action\n", - "The second action is the only action executed because it is the only condition that exactly matches the string\n", - "'Condition' when accounting for case-sensitivity." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "switch -CaseSensitive ('Condition')\n", - "{\n", - " 'condition' {'First Action'}\n", - " 'Condition' {'Second Action'}\n", - " 'conditioN' {'Third Action'}\n", - "}" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Modify the below statement so 'kick' will work considering that the switch statement is Case Sensitive." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "$myValue = \"kick\"\n", - "\n", - "switch -CaseSensitive ($myValue)\n", - "{\n", - " 'punch' { 'I punched you for 50 damage' }\n", - " 'KICK' { 'I kicked you for 50 damage' }\n", - " 'assasinate' { 'I assasinated you'}\n", - "}\n", - "\n", - "Output:\n", - "Normal match\n", - "Zero or more wildcard chars.\n", - "Range and set of chars.\n", - "Single char. wildcard" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Section 8.3: Switch Statement with Wildcard Parameter\n", - "\n", - "The -Wildcard parameter allows switch statements to perform wildcard matching against conditions." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Example:\n", - "```powershell\n", - "switch -Wildcard ('Condition')\n", - "{\n", - " 'Condition' {'Normal match'}\n", - " 'Condit*' {'Zero or more wildcard chars.'}\n", - " 'C[aoc]ndit[f-l]on' {'Range and set of chars.'}\n", - " 'C?ndition' {'Single char. wildcard'}\n", - " 'Test*' {'No match'}\n", - "}\n", - "```\n", - "\n", - "Output:
\n", - "Normal match
\n", - "Zero or more wildcard chars.
\n", - "Range and set of chars.
\n", - "Single char. wildcard
\n", - "No Match" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "switch -Wildcard ('Condition')\n", - "{\n", - " 'Condition' {'Normal match'}\n", - " 'Condit*' {'Zero or more wildcard chars.'}\n", - " 'C[aoc]ndit[f-l]on' {'Range and set of chars.'}\n", - " 'C?ndition' {'Single char. wildcard'}\n", - " 'Test*' {'No match'}\n", - "}" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "\r\n", - "
\r\n", - " \r\n", - " \r\n", - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "a*: abc\n", - "*c: abc\n" - ] - } - ], - "source": [ - "switch -wildcard ('abc') {a* {\"a*: $_\"} *c {\"*c: $_\"}}" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Section 8.4: Switch Statement with File Parameter\n", - "\n", - "\n", - "The -file parameter allows the switch statement to receive input from a file. Each line of the file is evaluated by\n", - "the switch statement." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Example file input.txt:\n", - "condition\n", - "test" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Example switch statement:\n", - "```powershell\n", - "switch -file input.txt\n", - "{\n", - " 'condition' {'First Action'}\n", - " 'test' {'Second Action'}\n", - " 'fail' {'Third Action'}\n", - "}\n", - "```\n", - "\n", - "Output:
\n", - "First Action
\n", - "Second Action
" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "switch -file \"./sampledata/chapter8-4.txt\"\n", - "{\n", - " 'condition' {'First Action'}\n", - " 'test' {'Second Action'}\n", - " 'fail' {'Third Action'}\n", - "}" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Section 8.5: Simple Switch with Default Condition\n", - "The Default keyword is used to execute an action when no other conditions match the input value." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Example:\n", - "```powershell\n", - "switch('Condition')\n", - "{\n", - " 'Skip Condition'\n", - " {\n", - " 'First Action'\n", - " }\n", - " 'Skip This Condition Too'\n", - " {\n", - " 'Second Action'\n", - " }\n", - " Default\n", - " {\n", - " 'Default Action'\n", - " }\n", - "}\n", - "```\n", - "\n", - "Output:\n", - "Default Action" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - " Example" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "switch ('nomatch')\n", - "{\n", - " 'condition' {'First Action'}\n", - " 'test' {'Second Action'}\n", - " 'fail' {'Third Action'}\n", - " Default {\n", - " Write-Host -foreGroundColor Red 'This is the default if nothing matches.'\n", - " }\n", - "}" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Section 8.6: Switch Statement with Regex Parameter\n", - "The -Regex parameter allows switch statements to perform regular expression matching against conditions.\n", - "\n", - "Example:\n", - "```powershell\n", - "switch -Regex ('Condition')\n", - "{\n", - " 'Con\\D+ion' {'One or more non-digits'}\n", - " 'Conditio*$' {'Zero or more \"o\"'}\n", - " 'C.ndition' {'Any single char.'}\n", - " '^C\\w+ition$' {'Anchors and one or more word chars.'}\n", - " 'Test' {'No match'}\n", - "}\n", - "```\n", - "\n", - "Output:
\n", - "One or more non-digits
\n", - "Any single char.
\n", - "Anchors and one or more word chars.
" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "switch -Regex ('Cafadfasdfasfdfsition')\n", - "{\n", - " 'Con\\D+ion' {'One or more non-digits'} # Regex pattern : \\D+ ( '\\D' looks for any non-digit and '+' goes on indefinetely)\n", - " 'Conditio*$' {'Zero or more \"o\"'} # Regex pattern : o*$ ()\n", - " 'C.ndition' {'Any single char.'} # Regex pattern : . (period indicates ANY single character)\n", - " '^C\\w+ition$' {'Anchors and one or more word chars.'} # Regex pattern : ^C \\w+ $ (^C is the anchor point, \\w+ word with any length, $ end of regex)\n", - " 'Test' {'No match'} \n", - "}" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "switch -regex ('abc') {'(^a)(.*$)' {$matches}}" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Section 8.7: Simple Switch With Break\n", - "The break keyword can be used in switch statements to exit the statement before evaluating all conditions.
" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "switch('Condition')\n", - "{\n", - " 'Condition' {\n", - " 'First Action'\n", - " }\n", - " 'Condition' {\n", - " 'Second Action'\n", - " break\n", - " }\n", - " 'Condition'{\n", - " 'Third Action'\n", - " }\n", - "}" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Output:
\n", - "First Action
\n", - "Second Action

\n", - "Because of the break keyword in the second action, the third condition is not evaluated." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Section 8.8: Switch Statement with Exact Parameter\n", - "\n", - "The -Exact parameter enforces switch statements to perform exact, case-insensitive matching against string conditions.\n", - "\n", - "Example:
\n", - "```powershell\n", - "switch -Exact ('Condition')\n", - "{\n", - " 'condition' {'First Action'}\n", - " 'Condition' {'Second Action'}\n", - " 'conditioN' {'Third Action'}\n", - " '^*ondition$' {'Fourth Action'}\n", - " 'Conditio*' {'Fifth Action'}\n", - "}\n", - "```\n", - "\n", - "Output:
\n", - "First Action
\n", - "Second Action
\n", - "Third Action

\n", - "The first through third actions are executed because their associated conditions matched the input. The regex and\n", - "wildcard strings in the fourth and fifth conditions fail matching.

\n", - "Note that the fourth condition would also match the input string if regular expression matching was being\n", - "performed, but was ignored in this case because it is not." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "switch -Exact -regex ('Condition')\n", - "{\n", - " 'condition' {'First Action'}\n", - " 'Condition' {'Second Action'}\n", - " 'conditioN' {'Third Action'}\n", - " '^Condition$' {'Fourth Action'}\n", - " 'Conditio*' {'Fifth Action'}\n", - "}" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - " \n", - "```powershell\n", - "$myInput = 0\n", - "switch(`myInput) {\n", - " # because the result of the expression, 4,\n", - " # does not equal our input this block should not be run.\n", - " (2+2) { 'True. 2 +2 = 4' }\n", - " # because the result of the expression, 0,\n", - " # does equal our input this block should be run.\n", - " (2-2) { 'True. 2-2 = 0' }\n", - " # because our input is greater than -1 and is less than 1\n", - " # the expression evaluates to true and the block should be run.\n", - " { $_ -gt -1 -and $_ -lt 1 } { 'True. Value is 0' }\n", - "}\n", - "```" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "```powershell\n", - "$$$string1 = \"test\"\n", - "$string2 = \"test\"\n", - "$string3 = \"test\"\n", - "```" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "## Section 8.9: Switch Statement with Expressions\n", - "\n", - "Conditions can also be expressions:\n", - "```powershell\n", - "#$$\n", - "$myInput = 0\n", - "switch($myInput) {\n", - " # because the result of the expression, 4,\n", - " # does not equal our input this block should not be run.\n", - " (2+2) { 'True. 2 +2 = 4' }\n", - " # because the result of the expression, 0,\n", - " # does equal our input this block should be run.\n", - " (2-2) { 'True. 2-2 = 0' }\n", - " # because our input is greater than -1 and is less than 1\n", - " # the expression evaluates to true and the block should be run.\n", - " { $_ -gt -1 -and $_ -lt 1 } { 'True. Value is 0' }\n", - "}\n", - "```\n", - "\n", - "Output
\n", - "True. 2-2 = 0
\n", - "True. Value is 0" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "function returnValue {\n", - " return 5\n", - "}\n", - "\n", - "$myInput = 0\n", - "switch($myInput) {\n", - " # because the result of the expression, 4,\n", - " # does not equal our input this block should not be run.\n", - " (returnValue) { 'True. 2 +2 = 4' }\n", - " # because the result of the expression, 0,\n", - " # does equal our input this block should be run.\n", - " (2-2) { 'True. 2-2 = 0' }\n", - " # because our input is greater than -1 and is less than 1\n", - " # the expression evaluates to true and the block should be run.\n", - " { $_ -gt -1 -and $_ -lt 1 } { 'True. Value is 0' }\n", - "}" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "switch (8) {\n", - " {$_ -gt 3} {'greater than three'}\n", - " {$_ -gt 7} {'greater than 7'}\n", - "}" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - " Advanced Switch Statements" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "switch(1..6) {\n", - " {$_ % 2} {\"Odd $_\"; continue}\n", - " 4 {\"FOUR $_\"}\n", - " default {\"Even $_\"}\n", - "}\n", - "\n", - "switch -wildcard (Get-ChildItem c:\\windows) {\n", - " *.dll {$dll++}\n", - " *.txt {$txt++}\n", - " *.log {$log++}\n", - "}\n", - "\"dll $dll txt $txt log $log\"\n", - "\n", - "switch ($options){\n", - " '-a' { $a=$true }\n", - " '-b' { [void] $switch.MoveNext(); $b= $switch.Current }\n", - " '-c' { $c=$true }\n", - " '-d' { $d=$true }\n", - "}" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - " If you want to watch an explanation video. Run the cell below (Not available yet)" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - " " - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "## Run this if you want to see explaination of the top\n", - "Import-Module \"./modules/tutorial.psm1\"; embedYoutube -youtubeId \"JcrLNVwplAI\" | Out-Display" - ] - }, - { - "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/1 - Tutorial with Videos/Chapter 09 - Strings.ipynb b/Notebooks/PowerShell/1 - Tutorial with Videos/Chapter 09 - Strings.ipynb deleted file mode 100755 index 9665e2d..0000000 --- a/Notebooks/PowerShell/1 - Tutorial with Videos/Chapter 09 - Strings.ipynb +++ /dev/null @@ -1,536 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Chapter 9: Strings\n", - "\n", - "This tutorial was sourced from the great work done by http://GoalKicker.com/PowerShellBook and the content is written by the beautiful people at Stack Overflow.\n", - "\n", - "### Table of Contents\n", - "1. [Multiline string](#1)\n", - "2. [Here-string](#2)\n", - "3. [Concatenating strings](#3)\n", - "4. [Creating a basic string](#4)\n", - "5. [Special characters](#5)\n", - "6. [Creating a basic string](#6)\n", - "7. [Format string](#7)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Section 9.1: Multiline string" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "There are multiple ways to create a multiline string in PowerShell:
\n", - "\n", - "The '\\n' is the \"Line Feed\" and '\\r' is the carriage return.
Different operating systems will handle new lines in a different way.\n", - "[Documentation Here](https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_special_characters?view=powershell-7)\n", - "\n", - "| OS | Command | Description |\n", - "|---|---|---|\n", - "|Windows|
\\`r\\`n
or
[Environment]::NewLine | Expects a newline to be combination of two characters. Im at the end of the line. goto the next line. |\n", - "| Linux |
\\`n
or
[Environment]::NewLine | Uses a single '\\n' for a new line.\n", - "| Classic Mac OS |
\\`r
or
| Uses a single '\\r' for a new line." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "On windows\n", - "```powershell\n", - "\"Hello`r`nWorld\" or \"Hello{0}World\" -f [environment]::NewLine\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "[environment]::NewLine -eq \"`r`n\"\n", - "\"`nHello`r`nWorld\"\n", - "\"`nHello{0}World\" -f [environment]::NewLine" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "On Linux\n", - "```powershell\n", - "\"Hello`nWorld\" or \"Hello{0}World\" -f [environment]::NewLine\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "[environment]::NewLine -eq \"`n\"\n", - "\"`nHello`nWorld\"\n", - "\"`nHello{0}World\" -f [environment]::NewLine" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Create a linebreak while defining a string (before closing quote)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "\"Hello World\"" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Using a here-string. This is the most common technique." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "@\"\n", - "Hello\n", - "World\n", - "\"@" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Section 9.2: Here-string\n", - "Here-strings are very useful when creating multiline strings. One of the biggest benefits compared to other\n", - "multiline strings are that you can use quotes without having to escape them using a backtick." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Here-string\n", - "\n", - "Here-strings begin with @\" and a linebreak and end with \"@ on its own line.
\n", - "(\"@must be first characters on the line, not even whitespace/tab).\n", - "```powershell\n", - "@\"\n", - "Simple\n", - " Multiline string\n", - "with \"quotes\"\n", - "\"@\n", - "```\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "$htmlCode = @\"\n", - "\n", - "\n", - "\n", - "\"@\n", - "\n", - "$htmlCode | Out-Display" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Literal here-string" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "You could also create a literal here-string by using single quotes, when you don't want any expressions to be\n", - "expanded just like a normal literal string.\n", - "```powershell\n", - "@'\n", - "The following line won't be expanded\n", - "$(Get-Date)\n", - "because this is a literal here-string\n", - "'@\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "@'\n", - "The following line won't be expanded\n", - "$(Get-Date)\n", - "because this is a literal here-string\n", - "'@" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Another Tip\n", - "If you want to insert variables into a multi-line string. You cant use a literal string. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "@\"\n", - "Simple\n", - " Multiline string\n", - "with \"quotes\"\n", - "\"@" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Section 9.3: Concatenating strings\n", - "Using variables in a string" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "You can concatenate strings using variables inside a double-quoted string. This does not work with properties.\n", - "```powershell\n", - "#$$ powershell code\n", - "$string1 = \"Power\"\n", - "$string2 = \"Shell\"\n", - "\"Greetings from $string1$string2\"\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "#$$ powershell code\n", - "$string1 = \"Power\"\n", - "$string2 = \"Shell\"\n", - "\"Greetings from $string1$string2\"" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Using the + operator\n", - "You can also join strings using the + operator.\n", - "```powershell\n", - "#$$ powershell code\n", - "$string1 = \"Greetings from\"\n", - "$string2 = \"PowerShell\"\n", - "$string1 + \" \" + $string2\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "$string1 = \"Greetings from\"\n", - "$string2 = \"PowerShell\"\n", - "$string1 + \" \" + $string2" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This also works with properties of objects.\n", - "```powershell\n", - "\"The title of this console is '\" + $host.Name + \"'\"\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "\"The title of this console is '\" + $host.Name + \"'\"" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Using subexpressions\n", - "The output/result of a subexpressions \\\\$() can be used in a string. This is useful when accessing properties of an\n", - "object or performing a complex expression. Subexpressions can contain multiple statements separated by\n", - "semicolon ;\n", - "```powershell\n", - "\"Tomorrow is $((Get-Date).AddDays(1).DayOfWeek)\"\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "\"Tomorrow is $((Get-Date).AddDays(1).DayOfWeek)\"" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Section 9.4: Special characters\n", - "When used inside a double-quoted string, the escape character (backtick `) represents a special character.
\n", - "[Documentation Here](https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_special_characters?view=powershell-7)\n", - "```powershell\n", - "`0 #Null\n", - "`a #Alert/Beep\n", - "`b #Backspace\n", - "`f #Form feed (used for printer output)\n", - "`n #New line\n", - "`r #Carriage return\n", - "`t #Horizontal tab\n", - "`v #Vertical tab (used for printer output)\n", - "```" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Example:\n", - "```powershell\n", - "> \"This`tuses`ttab`r`nThis is on a second line\"\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "\"This`tuses`ttab`r`nThis is on a second line\"" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "You can also escape special characters with special meanings:\n", - "```\n", - "`# #Comment-operator\n", - "`$ #Variable operator\n", - "`` #Escape character\n", - "`' #Single quote\n", - "`\" #Double quote\n", - "```" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Section 9.5: Creating a basic string\n", - "\n", - "### String\n", - "Strings are created by wrapping the text with double quotes. Double-quoted strings can evaluate variables and\n", - "special characters.\n", - "```powershell\n", - "#$$ Powershell Code\n", - "$myString = \"Some basic text\"\n", - "$mySecondString = \"String with a $variable\"\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "$myString = \"Some basic text\"\n", - "$mySecondString = \"String with a $myString\"\n", - "\n", - "$mySecondString" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To use a double quote inside a string it needs to be escaped using the escape character, backtick (`). Single quotes can be used inside a double-quoted string.\n", - "```powershell\n", - "$myString = \"A `\"double quoted`\" string which also has 'single quotes'.\"\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "$myString = \"A `\"double quoted`\" string which also has 'single quotes'.\"\n", - "$myString" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Literal String" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Literal strings are strings that doesn't evaluate variables and special characters. It's created using single quotes.\n", - "```powershell\n", - "#$$ Powershell Code\n", - "$myLiteralString = 'Simple text including special characters (`n) and a $variable-reference'\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "$myLiteralString = 'Simple text including special characters (`n) and a $variable-reference'" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To use single quotes inside a literal string, use double single quotes or a literal here-string. Double quotes can be\n", - "used safely inside a literal string\n", - "```powershell\n", - "$myLiteralString = 'Simple string with ''single quotes'' and \"double quotes\".'\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "$myLiteralString = 'Simple string with ''single quotes'' and \"double quotes\".'\n", - "$myLiteralString" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Section 9.6: Format string\n", - "```powershell\n", - "#$$ Powershell Code\n", - "$hash = @{ city = 'Berlin' }\n", - "$result = 'You should really visit {0}' -f $hash.city\n", - "Write-Host $result #prints \"You should really visit Berlin\"\n", - "```\n", - "Format strings can be used with the -f operator or the static [String]::Format(string format, args) .NET\n", - "method." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "$hash = @{ \n", - " city = 'Berlin'\n", - " anothercity = 'Miami'\n", - "}\n", - "$result = 'You should really visit {0} and {1}' -f $hash.city,$hash.anothercity\n", - "Write-Host $result #prints \"You should really visit Berlin\"" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - " If you want to watch an explanation video. Run the cell below (Not available yet)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "## Run this if you want to see explaination of the top\n", - "Import-Module \"./modules/tutorial.psm1\"; embedYoutube -youtubeId \"bwHYfdi3kKY\" | Out-Display" - ] - } - ], - "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": false, - "toc-showmarkdowntxt": false - }, - "nbformat": 4, - "nbformat_minor": 4 -} diff --git a/Notebooks/PowerShell/1 - Tutorial with Videos/Chapter 10 - HashTables.ipynb b/Notebooks/PowerShell/1 - Tutorial with Videos/Chapter 10 - HashTables.ipynb deleted file mode 100755 index 862fa48..0000000 --- a/Notebooks/PowerShell/1 - Tutorial with Videos/Chapter 10 - HashTables.ipynb +++ /dev/null @@ -1,449 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Chapter 10: HashTables\n", - "\n", - "This tutorial was sourced from the great work done by http://GoalKicker.com/PowerShellBook and the content is written by the beautiful people at Stack Overflow.\n", - "\n", - "A Hash Table is a structure which maps keys to values. See [Hash Table](https://en.wikipedia.org/wiki/Hash_table) for details.\n", - "\n", - "### Table of Contents\n", - "1. [Section 10.1: Access a hash table value by key](#1)\n", - "2. [Creating a Hash Table](#2)\n", - "3. [Add a key value pair to an existing hash table](#3)\n", - "4. [Remove a key value pair from an existing hash table](#4)\n", - "5. [Enumerating through keys and Key-Value Pairs](#5)\n", - "6. [Looping over a hash table](#6)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Section 10.1: Access a hash table value by key\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### An example of defining a hash table and accessing a value by the key\n", - "\n", - "\n", - "```powershell\n", - "$hashTable = @{\n", - " Key1 = 'Value1'\n", - " Key2 = 'Value2'\n", - "}\n", - "$hashTable.Key1\n", - "#output\n", - "Value1\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "$hashTable = @{\n", - " Key1 = 'Value1'\n", - " Key2 = 'Value2'\n", - "}\n", - "$hashTable.Key1" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "$family = @{\n", - " dad = \"bob\"\n", - " mom = \"susan\"\n", - " daughter = \"lizzy\"\n", - "}\n", - "$family.'daughter'" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### An example of accessing a key with invalid characters for a property name:\n", - "\n", - "\n", - "```powershell\n", - "$hashTable = @{\n", - " 'Key 1' = 'Value3'\n", - " Key2 = 'Value4'\n", - "}\n", - "$hashTable.'Key 1'\n", - "#Output\n", - "Value3\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# $hashTable = @{\n", - " 'Key 1' = 'Value3'\n", - " Key2 = 'Value4'\n", - "}\n", - "$hashTable.'Key 1'" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "#$family\n", - "\n", - "#$family.'step brother' = \"sam\"\n", - "$family" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Section 10.2: Creating a Hash Table\n", - "#### Example of creating an empty HashTable:\n", - "```powershell\n", - "$hashTable = @{}\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "$hashTable = @{}" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Example of creating a HashTable with data:\n", - "```powershell\n", - "$hashTable = @{\n", - " Name1 = 'Value'\n", - " Name2 = 'Value'\n", - " Name3 = 'Value3'\n", - "}\n", - "```" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### An example, to add a \"Key2\" key with a value of \"Value2\" to the hash table using the Add method:\n", - "\n", - "\n", - "```powershell\n", - "$hashTable = @{\n", - " Key1 = 'Value1'\n", - "}\n", - "$hashTable.Add(\"Key2\", \"Value2\")\n", - "$hashTable\n", - "#Output\n", - "Name Value\n", - "---- -----\n", - "Key1 Value1\n", - "Key2 Value2\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "$hashTable = @{\n", - " Key1 = 'Value1'\n", - "}\n", - "$hashTable.Add(\"Key2\", \"Value2\")\n", - "#$hashTable\n", - "$hashTable" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "$hashTable.newProperty = \"test\"" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "#$family.'step sister' = \"cynthia\"\n", - "$family" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Section 10.3: Add a key value pair to an existing hash table\n", - "#### An example, to add a \"Key2\" key with a value of \"Value2\" to the hash table, using the addition operator:\n", - "\n", - "```powershell\n", - "$hashTable = @{\n", - " Key1 = 'Value1'\n", - "}\n", - "$hashTable += @{Key2 = 'Value2'}\n", - "$hashTable\n", - "#Output\n", - "Name Value\n", - "---- -----\n", - "Key1 Value1\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "$hashTable = @{\n", - " Key1 = 'Value1'\n", - "}\n", - "$hashTable\n", - "$hashTable += @{Key2 = 'value2'}\n", - "#$hashTable += @{Key2 = 'Value2'}\n", - "#$hashTable\n", - "$hashTable" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "$hashTable" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Section 10.4: Remove a key value pair from an existing hash table\n", - "#### An example, to remove a \"Key2\" key with a value of \"Value2\" from the hash table, using the remove operator:\n", - "\n", - "```powershell\n", - "$hashTable = @{\n", - " Key1 = 'Value1'\n", - " Key2 = 'Value2'\n", - "}\n", - "$hashTable.Remove(\"Key2\", \"Value2\")\n", - "$hashTable\n", - "#Output\n", - "Name Value\n", - "---- -----\n", - "Key1 Value1\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "$family" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "$family.Remove('dad')" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "$family" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Section 10.5: Enumerating through keys and Key-Value Pairs\n", - "#### Enumerating through Keys\n", - "\n", - "```powershell\n", - "foreach ($key in $var1.Keys) {\n", - " $value = $var1[$key]\n", - " # or\n", - " $value = $var1.$key\n", - "}\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "foreach ($key in $family.Keys) {\n", - " Write-Host \"key: $key, $($family.$key)\"\n", - "}" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Enumerating through Key-Value Pairs\n", - "\n", - "```powershell\n", - "foreach ($keyvaluepair in $var1.GetEnumerator()) {\n", - " $key1 = $_.Key1\n", - " $val1 = $_.Val1\n", - " ```" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "\n", - "foreach ($kvp in $family.GetEnumerator() ) {\n", - " Write-Host $kvp.key\",\"$kvp.value\n", - "}" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Section 10.6: Looping over a hash table\n", - "\n", - "```powershell\n", - "$hashTable = @{\n", - " Key1 = 'Value1'\n", - " Key2 = 'Value2'\n", - " }\n", - "foreach($key in $hashTable.Keys)\n", - "{\n", - " $value = $hashTable.$key\n", - " Write-Output \"$key : $value\"\n", - "}\n", - "#Output\n", - "Key1 : Value1\n", - "Key2 : Value2\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "foreach($key in $family.Keys)\n", - "{\n", - " $value = $family.$key\n", - " Write-Output \"$key : $value\"\n", - "}" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - " If you want to watch an explanation video. Run the cell below (Not available yet)" - ] - }, - { - "cell_type": "code", - "execution_count": 110, - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - " " - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "## Run this if you want to see explaination of the top\n", - "Import-Module \"./modules/tutorial.psm1\"; embedYoutube -youtubeId \"RXfmG5-3_NM\" | Out-Display" - ] - }, - { - "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": false, - "toc-showmarkdowntxt": true - }, - "nbformat": 4, - "nbformat_minor": 4 -} diff --git a/Notebooks/PowerShell/1 - Tutorial with Videos/Chapter 11 - Working with Objects.ipynb b/Notebooks/PowerShell/1 - Tutorial with Videos/Chapter 11 - Working with Objects.ipynb deleted file mode 100755 index 72568b9..0000000 --- a/Notebooks/PowerShell/1 - Tutorial with Videos/Chapter 11 - Working with Objects.ipynb +++ /dev/null @@ -1,689 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Chapter 11: Working with Objects\n", - "\n", - "This tutorial was sourced from the great work done by http://GoalKicker.com/PowerShellBook and the content is written by the beautiful people at Stack Overflow.\n", - "\n", - "### Table of Contents\n", - "1. [Examining an object](#1)\n", - "2. [Updating Objects](#2)\n", - "3. [Creating a new object](#3)\n", - "4. [Creating Instances of Generic Classes](#4)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Section 11.1: Examining an object\n", - "\n", - "Now that you have an object, it might be good to figure out what it is. You can use the Get-Member cmdlet to see\n", - "what an object is and what it contains:\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The following command will list the TypeName of the item, followed by a list of properties and methods the object has:\n", - "```powershell\n", - "Get-Item (pwd) | Get-Member\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Get-Item (pwd) | Get-Member" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Another example" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "(pwd) | Get-Member" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Get-Item (pwd) | Get-Member" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "(Get-Item (pwd)).GetFiles()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Another way to get the type of an object is to use the GetType method, like so:\n", - "\n", - "```powershell\n", - "$Object = Get-Item (pwd)\n", - "$Object.GetType()\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "$Object = Get-Item (pwd)\n", - "$object.GetType() | Get-Member" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "((pwd) | Get-Item).getType() | FL *" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To view a list of properties the object has, along with their values, you can use the Format-List cmdlet with its\n", - "Property parameter set to: * (meaning all).\n", - "Here is an example, with the resulting output:\n", - "```powershell\n", - "Get-Item (pwd) | Format-List -Property *\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Get-Item (pwd) | Format-List -Property *" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Get-Item \"$(pwd)/Chapter 1 - Getting started with PowerShell.ipynb\" | Format-List -Property *" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Section 11.2: Updating Objects" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Adding Properties\n", - "\n", - "If you'd like to add properties to an existing object, you can use the Add-Member cmdlet. With PSObjects, values are\n", - "kept in a type of \"Note Properties\"\n", - "\n", - "```powershell\n", - "$object = New-Object -TypeName PSObject -Property @{\n", - " Name = \"bob\"\n", - " ID = 12\n", - " Address = $null\n", - " }\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "$object = New-Object -TypeName PSObject -Property @{\n", - " Name = \"bob\"\n", - " ID = 12\n", - " Address = $null\n", - " }\n", - "$object | FL" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Add-Member -InputObject $object -Name \"anotherProperty2\" -Value \"stuff\" -MemberType NoteProperty\n", - "# Returns\n", - "$Object | FL" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "You can also add properties with Select-Object Cmdlet (so called calculated properties):\n", - "\n", - "```powershell\n", - "$newObject = $Object | Select-Object *, @{label='SomeOtherProp'; expression={'Another value'}}\n", - "$newObject\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "$newObject = $Object | Select-Object *, @{label='SomeOtherProp'; expression={'Another value'}}\n", - "$newObject" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Shorter version\n", - "\n", - "```powershell\n", - "$newObject = $Object | Select *,@{l='SomeOtherProp';e={'Another value'}}\n", - "$newObject\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": 351, - "metadata": {}, - "outputs": [], - "source": [ - "$newObject = $Object | Select *,@{l='SomeOtherProp';e={'Another value'}}\n", - "$newObject" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Removing properties" - ] - }, - { - "cell_type": "code", - "execution_count": 354, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "Address anotherProperty2 SomeOtherProp\n", - "------- ---------------- -------------\n", - " stuff Another value\n", - "\n" - ] - } - ], - "source": [ - "$newObject = $newObject | Select-Object * -ExcludeProperty ID, Name\n", - "$newObject" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Section 11.3: Creating a new object\n", - "\n", - "PowerShell, unlike some other scripting languages, sends objects through the pipeline. What this means is that\n", - "when you send data from one command to another, it's essential to be able to create, modify, and collect objects.

\n", - "Creating an object is simple. Most objects you create will be custom objects in PowerShell, and the type to use for\n", - "that is PSObject. PowerShell will also allow you to create any object you could create in .NET.

\n", - "Here's an example of creating a new objects with a few properties:" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Option 1: New-Object\n", - "\n", - "```powershell\n", - "$newObject = New-Object -TypeName PSObject -Property @{\n", - " Name = $env:username\n", - " ID = 12\n", - " Address = $null\n", - "}\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": 355, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "ID Address Name\n", - "-- ------- ----\n", - "12 \n", - "\n" - ] - } - ], - "source": [ - "$newObject = New-Object -TypeName PSObject -Property @{\n", - " Name = $env:username\n", - " ID = 12\n", - " Address = $null\n", - "}\n", - "$newObject" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "You can store the object in a variable by prefacing the command with newObject =\n", - "You may also need to store collections of objects. This can be done by creating an empty collection variable, and\n", - "adding objects to the collection, like so:\n", - "\n", - "```powershell\n", - "$newCollection = @()\n", - "$newCollection += New-Object -TypeName PSObject -Property @{\n", - " Name = $env:username\n", - " ID = 12\n", - " Address = $null\n", - "}\n", - "```\n", - "You may then wish to iterate through this collection object by object. To do that, locate the Loop section in the\n", - "documentation." - ] - }, - { - "cell_type": "code", - "execution_count": 356, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "ID Address Name\n", - "-- ------- ----\n", - "12 \n", - "\n" - ] - } - ], - "source": [ - "$newCollection = @()\n", - "$newCollection += New-Object -TypeName PSObject -Property @{\n", - " Name = $env:username\n", - " ID = 12\n", - " Address = $null\n", - "}\n", - "$newCollection" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Another Example" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "$newCollection = @()\n", - "$newCollection += New-Object -TypeName PSObject -Property @{\n", - " Name = \"bob\"\n", - " ID = 12\n", - " Address = $null\n", - "}\n", - "$newCollection += New-Object -TypeName PSObject -Property @{\n", - " Name = \"amanda\"\n", - " ID = 13\n", - " Address = $null\n", - "}\n", - "$newCollection" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Option 2: Select-Object\n", - "\n", - "A less common way of creating objects that you'll still find on the internet is the following:\n", - "\n", - "```powershell\n", - "$newObject = 'unuseddummy' | Select-Object -Property Name, ID, Address\n", - "$newObject.Name = $env:username\n", - "$newObject.ID = 12\n", - "$newObject\n", - "\n", - "# Returns\n", - "PS> $newObject\n", - "Name ID Address\n", - "---- -- -------\n", - "nem 12\n", - "\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "$newObject = 'unuseddummy'\n", - "$newObject = $newObject | Select-Object -Property Name, ID, Address\n", - "$newObject" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "$newObject.Name = \"bob\"\n", - "$newObject.ID = 12\n", - "$newObject" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "$newObject = 'unuseddummy' | Select-Object -Property Name, ID, Address\n", - "$newObject.Name = $env:username\n", - "$newObject.ID = 12\n", - "$newObject" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Option 3: pscustomobject type accelerator (PSv3+ required)\n", - "\n", - "The ordered type accelerator forces PowerShell to keep our properties in the order that we defined them. You don't\n", - "need the ordered type accelerator to use [PSCustomObject]:\n", - "\n", - "```powershell\n", - "$newObject = [PSCustomObject][Ordered]@{\n", - " Name = $env:Username\n", - " ID = 12\n", - " Address = $null\n", - "}\n", - "$newObject\n", - "\n", - "# Returns\n", - "PS> $newObject\n", - "Name ID Address\n", - "---- -- -------\n", - "nem 12\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "$newObject = [PSCustomObject][Ordered]@{\n", - " Address = $null\n", - " Name = $env:Username\n", - " ID = 12\n", - "}\n", - "$newObject" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "$newObject | Select-Object @('Name')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Section 11.4: Creating Instances of Generic Classes\n", - "Note: examples written for PowerShell 5.1 You can create instances of Generic Classes\n", - "\n", - "```powershell\n", - "#Nullable System.DateTime\n", - "[Nullable[datetime]]$nullableDate = Get-Date -Year 2012\n", - "$nullableDate\n", - "$nullableDate.GetType().FullName\n", - "$nullableDate = $null\n", - "$nullableDate\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "$nullableDate = Get-Date -Year 2012\n", - "$nullableDate.Gettype()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "#Nullable System.DateTime\n", - "[Nullable[datetime]]$nullableDate = Get-Date -Year 2012\n", - "\n", - "Write-Output \"DateTime: $nullableDate\"\n", - "Write-Output \"Type: $($nullableDate.GetType().FullName)\"\n", - "$nullableDate = $null\n", - "Write-Output \"Null Value: $nullableDate\"" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This example shows if nullable was not specified. You will get an error when powershell attempts to convert object to null\n", - "\n", - "```powershell\n", - "#Normal System.DateTime\n", - "[datetime]$aDate = Get-Date -Year 2013\n", - "$aDate\n", - "$aDate.GetType().FullName\n", - "$aDate = $null #Throws exception when PowerShell attempts to convert null to\n", - "\n", - "#Gives the output:\n", - "Saturday, 4 August 2012 08:53:02\n", - "System.DateTime\n", - "Sunday, 4 August 2013 08:53:02\n", - "System.DateTime\n", - "Cannot convert null to type \"System.DateTime\".\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "[datetime]$aDate = Get-Date -Year 2013\n", - "$aDate\n", - "$aDate.GetType().FullName\n", - "$aDate = $null #Throws exception when PowerShell attempts to convert null to" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Generic Collections are also possible\n", - "\n", - "```powershell\n", - "[System.Collections.Generic.SortedDictionary[int, String]]$dict =\n", - "[System.Collections.Generic.SortedDictionary[int, String]]::new()\n", - "$dict.GetType().FullName\n", - "$dict.Add(1, 'a')\n", - "$dict.Add(2, 'b')\n", - "$dict.Add(3, 'c')\n", - "$dict.Add('4', 'd') #powershell auto converts '4' to 4\n", - "$dict.Add('5.1', 'c') #powershell auto converts '5.1' to 5\n", - "$dict\n", - "$dict.Add('z', 'z') #powershell can't convert 'z' to System.Int32 so it throws an error\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "$dict = [System.Collections.Generic.SortedDictionary[int, String]]::new()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "$dict.GetType() | Get-Member" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "$dict.Add(1, 'a')\n", - "$dict.Add(2, 'b')\n", - "$dict.Add(3, 'c')\n", - "$dict.Add('4', 'd') #powershell auto converts '4' to 4\n", - "$dict.Add('5.1', 'c') #powershell auto converts '5.1' to 5\n", - "$dict" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "$dict.Add('z', 'z') #powershell can't convert 'z' to System.Int32 so it throws an error" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "$dict.3 = \"test\"\n", - "$dict" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - " If you want to watch an explanation video. Run the cell below (Not available yet)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "## Run this if you want to see explaination of the top\n", - "Import-Module \"./modules/tutorial.psm1\"; embedYoutube -youtubeId \"ORQOy_utnTY\" | Out-Display" - ] - }, - { - "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": false, - "toc-showmarkdowntxt": true - }, - "nbformat": 4, - "nbformat_minor": 4 -} diff --git a/Notebooks/PowerShell/1 - Tutorial with Videos/PowerShellNotesForProfessionals.pdf b/Notebooks/PowerShell/1 - Tutorial with Videos/PowerShellNotesForProfessionals.pdf deleted file mode 100755 index 69f500c..0000000 Binary files a/Notebooks/PowerShell/1 - Tutorial with Videos/PowerShellNotesForProfessionals.pdf and /dev/null differ diff --git a/Notebooks/PowerShell/1 - Tutorial with Videos/modules/myScript.ps1 b/Notebooks/PowerShell/1 - Tutorial with Videos/modules/myScript.ps1 deleted file mode 100755 index 3ee08b0..0000000 --- a/Notebooks/PowerShell/1 - Tutorial with Videos/modules/myScript.ps1 +++ /dev/null @@ -1,3 +0,0 @@ -Write-Host "Script 1 Running" -Write-Host "Hello World!" -Write-Host "Hello Youtube" \ No newline at end of file diff --git a/Notebooks/PowerShell/1 - Tutorial with Videos/modules/tutorial.psm1 b/Notebooks/PowerShell/1 - Tutorial with Videos/modules/tutorial.psm1 deleted file mode 100755 index 7a10021..0000000 --- a/Notebooks/PowerShell/1 - Tutorial with Videos/modules/tutorial.psm1 +++ /dev/null @@ -1,21 +0,0 @@ -function embedYoutube { - param( - $youtubeId - ) - - $htmlCode = @" - -"@ - return $htmlCode -} \ No newline at end of file diff --git a/Notebooks/PowerShell/1 - Tutorial with Videos/sampledata/chapter8-4.txt b/Notebooks/PowerShell/1 - Tutorial with Videos/sampledata/chapter8-4.txt deleted file mode 100755 index 30d74d2..0000000 --- a/Notebooks/PowerShell/1 - Tutorial with Videos/sampledata/chapter8-4.txt +++ /dev/null @@ -1 +0,0 @@ -test \ No newline at end of file diff --git a/Notebooks/PowerShell/2 - Webinars/20200615 - Harnessing the Power of Jupyter Notebooks with Powershell/Agenda.ipynb b/Notebooks/PowerShell/2 - Webinars/20200615 - Harnessing the Power of Jupyter Notebooks with Powershell/Agenda.ipynb deleted file mode 100755 index 03c62fa..0000000 --- a/Notebooks/PowerShell/2 - Webinars/20200615 - Harnessing the Power of Jupyter Notebooks with Powershell/Agenda.ipynb +++ /dev/null @@ -1,197 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Agenda" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "

Introduction to Jupyter Notebook

" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
FilenameDescriptionStatusLast Tested
Getting-Started-README.ipynbIts highly recommended to follow this guide to get familiar with navigating and using Jupyter Notebooks. Last Tested: 6/16/2020
Word CloudIts highly recommended to follow this guide to get familiar with navigating and using Jupyter Notebooks. Last Tested: 6/16/2020
" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Scenarios" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "

Create your own custom API - New User Progress Tracker Form Example

\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
FilenameDescriptionStatus
New User Progress TrackerIn this scenario, we will create a user in MS Forms, and then populate an Excel file using Power-Automate.
From there we will query the Excel file using a custom API built in Power-Automate
" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "

MDATP

" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "

Query the MDATP with an advanced hunting query

\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
FilenameDescriptionStatus
Advanced Hunting QueryIts highly recommended to follow this guide to get familiar with navigating and using Jupyter Notebooks.
\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "

Pull a query from the public MDATP public Github repository

\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
FilenameDescriptionStatus
Query using MDATP Github.ipynbThis notebook will query the MDATP Github repository and pull the referenced link's raw data from Github to be used in querying the MDATP API
" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Azure Sentinel - Query Azure Sentinel " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Reporting" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "

Office 365 Email Activity Report using Device Code Authentication

\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
FilenameDescriptionStatus
E-mail Inbound/Outbound Activity StatisticsThis notebook will query the email statistics for the organization and plot the total email sent/received
" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "

Power BI Reporting Example

" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "#!html\n", - "\n", - "" - ] - } - ], - "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": true, - "toc-showtags": false - }, - "nbformat": 4, - "nbformat_minor": 4 -} diff --git a/Notebooks/PowerShell/2 - Webinars/20200615 - Harnessing the Power of Jupyter Notebooks with Powershell/WordCloud.ipynb b/Notebooks/PowerShell/2 - Webinars/20200615 - Harnessing the Power of Jupyter Notebooks with Powershell/WordCloud.ipynb deleted file mode 100755 index 3cbd6e4..0000000 --- a/Notebooks/PowerShell/2 - Webinars/20200615 - Harnessing the Power of Jupyter Notebooks with Powershell/WordCloud.ipynb +++ /dev/null @@ -1,100 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 19, - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "\n", - "\n", - "\n", - "\n", - "
created at TagCrowd.com
\n", - "\n", - "\n" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "#!html \n", - "\n", - "\n", - "\n", - "\n", - "\n", - "
created at TagCrowd.com
\n", - "\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/2 - Webinars/README.md b/Notebooks/PowerShell/2 - Webinars/README.md deleted file mode 100755 index e69de29..0000000 diff --git a/Notebooks/PowerShell/3 - Examples/Pipelines.ipynb b/Notebooks/PowerShell/3 - Examples/Pipelines.ipynb deleted file mode 100644 index de8acfa..0000000 --- a/Notebooks/PowerShell/3 - Examples/Pipelines.ipynb +++ /dev/null @@ -1,119 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "id": "premium-framing", - "metadata": {}, - "source": [ - "# Pipelines\n", - "#### Follow along and run the cells with shift + enter\n", - "- [Windows Powershell Cheatsheet](https://www.theochem.ru.nl/~pwormer/teachmat/PS_cheat_sheet.html)" - ] - }, - { - "cell_type": "markdown", - "id": "religious-collaboration", - "metadata": {}, - "source": [ - "\n", - "```powershell\n", - "Important: Cmdlets pass objects through pipelines, not a character stream as in Unix.\n", - "The pipeline character is $|, it must be followed by a cmdlet. The passed pipeline object is referred to by the automatic variable $_ and its member member_name is accordingly referred to by $_.member_name.\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "molecular-market", - "metadata": {}, - "outputs": [], - "source": [ - "$fruits = @('apple','banana','cherry','orange')\n", - "\n", - "$fruits | ForEach-Object {\n", - " Write-Host \"$_ - hello\"\n", - "}" - ] - }, - { - "cell_type": "markdown", - "id": "trained-transformation", - "metadata": {}, - "source": [ - "\n", - "```powershell\n", - "The treatment of the passed object $_ depends on the cmdlet it is passed to. To illustrate this, it is noted that a PowerShell string is an object with many methods, one of them being .contains(\"substr\"). The method returns true if the string contains \"substr\" and false if not. In the following example the stuff between curly brackets is a script block which is a sequence of executable statements. Now pass the very same string object to two different cmdlets:\n", - " \"a string\" | Foreach-Object {$_.contains(\"ri\")} # -> True\n", - " \"a string\" | Where-Object {$_.contains(\"ri\")} # -> \"a string\"\n", - "```" - ] - }, - { - "cell_type": "markdown", - "id": "intense-plenty", - "metadata": {}, - "source": [ - "\n", - "```powershell\n", - "The first cmdlet passes on the resulting boolean value which drops off the end of the pipeline and is then sent to the console.\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "transsexual-singer", - "metadata": {}, - "outputs": [], - "source": [ - "\"a string\" | Foreach-Object {$_.contains(\"ri\")} # -> True" - ] - }, - { - "cell_type": "markdown", - "id": "polished-hindu", - "metadata": {}, - "source": [ - "\n", - "```powershell\n", - "The second cmdlet uses the boolean result to decide what to do: if true the string is passed on in the pipeline (and as it is at the end, it is sent to the console). If false where-object stops the pipeline and no console output is generated.\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "fitting-tribe", - "metadata": {}, - "outputs": [], - "source": [ - "\"a string\" | Where-Object {$_.contains(\"ri\")} # -> \"a string\"" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "controlling-halifax", - "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": 5 -} diff --git a/Notebooks/PowerShell/Microsoft/AD/AD - Use CSV to update list of Employees.ipynb b/Notebooks/PowerShell/Microsoft/AD/AD - Use CSV to update list of Employees.ipynb deleted file mode 100755 index 7d09338..0000000 --- a/Notebooks/PowerShell/Microsoft/AD/AD - Use CSV to update list of Employees.ipynb +++ /dev/null @@ -1,77 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Use a CSV File to update an attribute with a list of employees in the CSV" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Get list of users and filter the distinguishedname, employeeid, and samaccountname" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Install-Module ActiveDirectory" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Import-Module ActiveDirectory" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "$adusers = get-aduser -filter * -properties distinguishedname,employeeid,samaccountname" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "\n", - "$hash = $adusers | group-object -ashashtable -property samaccountname\n", - "$collected = $adusers | select samaccountname,employeeid,distinguishedname\n", - "$csv = import-csv .\\sheet.csv\n", - "foreach ($row in $csv) {\n", - "$selected = $collected | where {$_.employeeid -eq $($row.employeeid)}\n", - "set-aduser $($selected.samaccountname) -title $($row.title)\n", - "}\n" - ] - } - ], - "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/Azure/README.md b/Notebooks/PowerShell/Microsoft/Azure/README.md deleted file mode 100755 index a61a5de..0000000 --- a/Notebooks/PowerShell/Microsoft/Azure/README.md +++ /dev/null @@ -1,3 +0,0 @@ - - -[ARM quick start templates](https://azure.microsoft.com/en-us/resources/templates/) \ No newline at end of file diff --git a/Notebooks/PowerShell/Microsoft/Demo Scenarios/Scenario 1 - New User Progress Tracker.ipynb b/Notebooks/PowerShell/Microsoft/Demo Scenarios/Scenario 1 - New User Progress Tracker.ipynb deleted file mode 100755 index 1479a6e..0000000 --- a/Notebooks/PowerShell/Microsoft/Demo Scenarios/Scenario 1 - New User Progress Tracker.ipynb +++ /dev/null @@ -1,517 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Scenario 1 - Create a New User in Azure using Power-Automate/Forms/Jupyter Notebooks\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Create User\n", - "HR User fills out new employee creation form" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Power Automate Form to grab the form response and insert response into Excel Table" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Query the Excel file stored on One-Drive via Jupyter Notebooks and REST API" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Build the JSON payload and headers" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "\r\n", - "
\r\n", - " \r\n", - " \r\n", - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\u001b[93mJSON Payload for REST Call\u001b[0m\n", - "{\n", - " \"Workflow\": \"list\"\n", - "}\n" - ] - } - ], - "source": [ - "$host.UI.RawUI.BufferSize = [System.Management.Automation.Host.Size]::new(200, 50) ## Corrects the output\n", - "$userDetails = @{ Workflow = \"list\" }\n", - "\n", - "$userDetails = ($userDetails | ConvertTO-JSON); \n", - "\n", - "$headers = @{\n", - " 'Content-Type' = \"application/json\"\n", - "}\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": 2, - "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", - " 70b48e14-883b-4d05-8582-a3b16a825114 Sarah David Finance Intern sara.david@jingtoso.com Completed Completed Completed\n", - " 410fcc3c-6a16-4ee5-840d-669665082cde Bob Smith IT Peon bob@jingtoso.com Completed Completed Not Started\n", - " d564504e-e43f-497f-a8cc-f2dbc3daf44b 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": "markdown", - "metadata": {}, - "source": [ - "### Get New-Users Tracker Status " - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "E-mail address Form Filled out HR Paperwork Computer assigned MFA Number setup O365 License assigned AD Group assignment\n", - "-------------- --------------- ------------ ----------------- ---------------- --------------------- -------------------\n", - "sara.david@jingtoso.com Completed Completed Completed Completed Completed Completed\n", - "bob@jingtoso.com Completed Completed Not Started Not Started Not Started Not Started\n", - "steve.smith@microsoft.com Completed Completed Completed Completed Not Started Not Started\n", - "\n" - ] - } - ], - "source": [ - "$filteredColumns = @('E-mail address','Form Filled out','HR Paperwork',\"Computer Assigned\",'MFA Number setup', 'O365 License assigned', 'AD Group assignment')\n", - "$Response | Select-Object -Property $filteredColumns | FT" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Clean up table to HTML" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
UserForm Filled OutHR Paperwork CompletedComputer AssignedMFA Number SetupLicense AssignedAD Group Assignment
Sarah David (sara.david@jingtoso.com)\n", - " Completed\n", - " Completed\n", - " Completed\n", - " Completed\n", - " Completed\n", - " Completed\n", - "
Bob Smith (bob@jingtoso.com)\n", - " Completed\n", - " Completed\n", - " Not Started\n", - " Not Started\n", - " Not Started\n", - " Not Started\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", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \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", - "
UserForm Filled OutHR Paperwork CompletedComputer AssignedMFA Number SetupLicense AssignedAD Group Assignment
$($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", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
Permission typePermissions (from least to most privileged)
Delegated (work or school account)EntitlementManagement.Read.All, EntitlementManagement.ReadWrite.All
Delegated (personal Microsoft Account)Not Supported
ApplicationNot Supported
" - ] - }, - { - "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", - " \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", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
TypeTitleDescription
DocumentationAdvanced Hunting APIThis is the documentation that refers to what permissions is required and request examples you can use to query the MDATP API
" - ] - }, - { - "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", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
TypeTitleDescription
DocumentationExtending Azure Sentinel: APIs, Integration and management automationIts highly recommended to follow this guide to get familiar with navigating and using Jupyter Notebooks.
Tech CommunityAccess Azure Sentinel Log Analytics via API (Part 1)@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.
" - ] - }, - { - "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", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
TypeTitleDescription
DocumentationAdvanced Hunting APIThis is the documentation that refers to what permissions is required and request examples you can use to query the MDATP API
" - ] - }, - { - "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", - " \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", - " \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", - " \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", - " \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