{"cells":[{"cell_type":"markdown","metadata":{"nteract":{"transient":{"deleting":false}}},"source":["# A Getting Started Guide for Azure Sentinel notebooks with C Sharp\r\n","**Notebook Version:** 1.0
\r\n","\r\n","**.Net Interactive installation is required! **:\r\n"," - To use this notebook, you will first need to install .Net Interactive. Instructions are located in this article ->[Azure Sentinel Notebooks + Powershell](https://aka.ms/sentinel/pwsh-notebooks).\r\n","\r\n","** About this notebook **: \r\n","\r\n","This notebook takes you through the basics needed to get started with C# notebooks that leverage Azure Sentinel data and APIs. It uses Azure Sentinel watchlist as an example to illustrate how to call REST APIs in C#.\r\n","\r\n","Lastly, don't forget to install .Net Interactive to use this notebook!"]},{"cell_type":"code","execution_count":null,"metadata":{"gather":{"logged":1600820739567}},"outputs":[],"source":["// Try your .NET Interactive - C# kernel\r\n","Console.WriteLine(\"I am in C# land!\")"]},{"cell_type":"code","execution_count":null,"metadata":{"collapsed":true,"gather":{"logged":1600820742947},"jupyter":{"outputs_hidden":false,"source_hidden":false},"nteract":{"transient":{"deleting":false}}},"outputs":[],"source":["// If you want to reference a library from Nuget\r\n","#r \"nuget:Octokit, 0.32.0\"\r\n","#r \"nuget:NodaTime, 2.4.6\"\r\n","using Octokit;\r\n","using NodaTime;\r\n","using NodaTime.Extensions;\r\n","using XPlot.Plotly;"]},{"cell_type":"code","execution_count":null,"metadata":{"collapsed":true,"gather":{"logged":1600820745683},"jupyter":{"outputs_hidden":false,"source_hidden":false},"nteract":{"transient":{"deleting":false}}},"outputs":[],"source":["// Get AAD access token using AZ CLI\r\n","#!pwsh\r\n","#Change the default colors \r\n","$Host.PrivateData.WarningBackgroundColor = \"White\"\r\n","$Host.PrivateData.WarningForegroundColor = \"Black\"\r\n","\r\n","$accessPass = az account get-access-token\r\n","$passJson = $accessPass | ConvertFrom-Json\r\n","$accessToken = $passJson[0].accessToken"]},{"cell_type":"code","execution_count":null,"metadata":{"collapsed":true,"gather":{"logged":1600820747843},"jupyter":{"outputs_hidden":false,"source_hidden":false},"nteract":{"transient":{"deleting":false}}},"outputs":[],"source":["// Transfer $accessToken in PowerShell to C# variable\r\n","#!csharp\r\n","#!share --from pwsh accessToken\r\n","string token = accessToken;"]},{"cell_type":"code","execution_count":null,"metadata":{"collapsed":true,"gather":{"logged":1600820750201},"jupyter":{"outputs_hidden":false,"source_hidden":false},"nteract":{"transient":{"deleting":false}}},"outputs":[],"source":["// class to read Sentinel workspace configuration: config.json in the directory\r\n","using System.IO;\r\n","using Newtonsoft.Json;\r\n","using Newtonsoft.Json.Linq;\r\n","\r\n","public class SentinelConfiguration\r\n","{\r\n"," public string TenantId { get; set; }\r\n"," public string SubscriptionId { get; set; }\r\n"," public string ResourceGroup { get; set; }\r\n"," public string WorkspaceId { get; set; }\r\n"," public string WorkspaceName { get; set; }\r\n","\r\n"," public SentinelConfiguration ReadConfiguration()\r\n"," {\r\n"," var config = new SentinelConfiguration();\r\n"," using (StreamReader reader = new StreamReader(\"config.json\"))\r\n"," {\r\n"," string json = reader.ReadToEnd();\r\n"," var jsonObj = JObject.Parse(json);\r\n","\r\n"," config.TenantId = (string)jsonObj[\"tenant_id\"];\r\n"," config.SubscriptionId = (string)jsonObj[\"subscription_id\"];\r\n"," config.ResourceGroup = (string)jsonObj[\"resource_group\"];\r\n"," config.WorkspaceId = (string)jsonObj[\"workspace_id\"];\r\n"," config.WorkspaceName = (string)jsonObj[\"workspace_name\"]; \r\n"," }\r\n","\r\n"," return config;\r\n"," }\r\n","}"]},{"cell_type":"code","execution_count":null,"metadata":{"collapsed":true,"gather":{"logged":1600820753177},"jupyter":{"outputs_hidden":false,"source_hidden":false},"nteract":{"transient":{"deleting":false}}},"outputs":[],"source":["// Define a class as Azure REST API Helper\r\n","using System.Net.Http;\r\n","\r\n","public class AzureResourceApiHelper\r\n","{\r\n"," public const string BaseUrl = \"https://management.azure.com\";\r\n"," public string AccessTokenTemplate = \"Bearer {0}\";\r\n","\r\n"," public string BuildResourceUrl(string azureResourceId)\r\n"," {\r\n"," return BaseUrl + azureResourceId;\r\n"," }\r\n","\r\n"," public HttpResponseMessage HttpGet(string token, string url)\r\n"," {\r\n"," HttpClient client = new HttpClient();\r\n"," client.DefaultRequestHeaders.Add(\"Authorization\", token);\r\n","\r\n"," HttpResponseMessage response = client.GetAsync(url).GetAwaiter().GetResult();\r\n"," return response;\r\n"," }\r\n","}"]},{"cell_type":"code","execution_count":null,"metadata":{"collapsed":true,"gather":{"logged":1600820756386},"jupyter":{"outputs_hidden":false,"source_hidden":false},"nteract":{"transient":{"deleting":false}}},"outputs":[],"source":["// Derfine a C# class for Azure Sentinel Watchlist\r\n","public class SentinelWatchlist\r\n","{\r\n"," private string watchlistsTemplate = \"/subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.OperationalInsights/workspaces/{2}/providers/Microsoft.SecurityInsights/watchlists?api-version=2019-01-01-preview\";\r\n"," private string watchlistTemplate = \"/subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.OperationalInsights/workspaces/{2}/providers/Microsoft.SecurityInsights/watchlists/{3}?api-version=2019-01-01-preview\";\r\n","\r\n"," // Get the watchlist by watchlist alias\r\n"," public HttpResponseMessage GetWatchlist(string accessToken, string watchlistAlias)\r\n"," {\r\n"," // Read config\r\n"," SentinelConfiguration config = new SentinelConfiguration();\r\n"," config = config.ReadConfiguration();\r\n","\r\n"," // call API\r\n"," AzureResourceApiHelper helper = new AzureResourceApiHelper();\r\n"," string resourceId = string.Format(watchlistTemplate, config.SubscriptionId, config.ResourceGroup,config.WorkspaceName, watchlistAlias);\r\n"," string url = helper.BuildResourceUrl(resourceId);\r\n"," string token = string.Format(helper.AccessTokenTemplate, accessToken);\r\n","\r\n"," return helper.HttpGet(token, url);\r\n"," }\r\n","\r\n"," // Get all watchlists\r\n"," public HttpResponseMessage GetAllWatchlists(string accessToken)\r\n"," {\r\n"," // Read config\r\n"," SentinelConfiguration config = new SentinelConfiguration();\r\n"," config = config.ReadConfiguration();\r\n","\r\n"," // call API\r\n"," AzureResourceApiHelper helper = new AzureResourceApiHelper();\r\n"," string resourceId = string.Format(watchlistsTemplate, config.SubscriptionId, config.ResourceGroup,config.WorkspaceName);\r\n"," string url = helper.BuildResourceUrl(resourceId);\r\n"," string token = string.Format(helper.AccessTokenTemplate, accessToken);\r\n","\r\n"," return helper.HttpGet(token, url);\r\n"," }\r\n","}"]},{"cell_type":"code","execution_count":null,"metadata":{"collapsed":true,"gather":{"logged":1600820759480},"jupyter":{"outputs_hidden":false,"source_hidden":false},"nteract":{"transient":{"deleting":false}}},"outputs":[],"source":["// Utils class\r\n","using System.Text.Json;\r\n","using Microsoft.AspNetCore.Html;\r\n","\r\n","public class Utils\r\n","{\r\n"," // Format json for readability\r\n"," public static string PrettyJson(string rawJson)\r\n"," {\r\n"," var options = new JsonSerializerOptions()\r\n"," {\r\n"," WriteIndented = true\r\n"," };\r\n","\r\n"," var jsonElement = System.Text.Json.JsonSerializer.Deserialize(rawJson);\r\n"," return System.Text.Json.JsonSerializer.Serialize(jsonElement, options);\r\n"," }\r\n","\r\n"," public static void TableDisplay()\r\n"," {\r\n"," Microsoft.DotNet.Interactive.Formatting.Formatter.Register>((dict, writter) =>\r\n"," {\r\n"," var headers = new List();\r\n"," headers.Add(th(\"Watchlist Alias\"));\r\n"," headers.Add(th(\"Updated Date\"));\r\n"," var rows = new List>();\r\n"," foreach (var pair in dict)\r\n"," {\r\n"," var cells = new List();\r\n"," cells.Add(td(pair.Key));\r\n"," cells.Add(td(pair.Value));\r\n"," rows.Add(cells);\r\n"," }\r\n"," \r\n"," var t = table(\r\n"," thead(headers),\r\n"," tbody(rows.Select(r => tr(r)))\r\n"," );\r\n","\r\n"," writter.Write(t);\r\n"," }, \"text/html\");\r\n"," }\r\n","}"]},{"cell_type":"code","execution_count":null,"metadata":{"collapsed":true,"gather":{"logged":1600820764004},"jupyter":{"outputs_hidden":false,"source_hidden":false},"nteract":{"transient":{"deleting":false}}},"outputs":[],"source":["// Get all watchlists, display alias\r\n","var wl = new SentinelWatchlist();\r\n","var responseMsg = wl.GetAllWatchlists(token);\r\n","string content = responseMsg.Content.ReadAsStringAsync().GetAwaiter().GetResult();\r\n","//Console.WriteLine(content);\r\n","dynamic x = Newtonsoft.Json.JsonConvert.DeserializeObject(content);\r\n","var allLists = x.value;\r\n","int index = 0;\r\n","var allWatchlist = new Dictionary();\r\n","\r\n","foreach(var watchlist in allLists)\r\n","{\r\n"," allWatchlist.Add(watchlist.properties.watchlistAlias.ToString(), watchlist.properties.updated.ToString());\r\n","}"]},{"cell_type":"code","execution_count":null,"metadata":{"collapsed":true,"gather":{"logged":1600820767444},"jupyter":{"outputs_hidden":false,"source_hidden":false},"nteract":{"transient":{"deleting":false}}},"outputs":[],"source":["// Display data in HTML table\r\n","Utils.TableDisplay();\r\n","allWatchlist"]},{"cell_type":"code","execution_count":null,"metadata":{"collapsed":true,"gather":{"logged":1600820771448},"jupyter":{"outputs_hidden":false,"source_hidden":false},"nteract":{"transient":{"deleting":false}}},"outputs":[],"source":["// if you have watchlist, then you may get a specific watchlist\r\n","if (allLists.Count > 0)\r\n","{\r\n"," // I set the index = 0, but you may select any index that is in the range of index\r\n"," var wlAlias = allWatchlist.Keys.FirstOrDefault();\r\n"," var responseMsg = wl.GetWatchlist(token, wlAlias);\r\n"," string content = responseMsg.Content.ReadAsStringAsync().GetAwaiter().GetResult();\r\n"," Console.WriteLine(Utils.PrettyJson(content));\r\n","}"]},{"cell_type":"code","execution_count":null,"metadata":{"collapsed":true,"jupyter":{"outputs_hidden":false,"source_hidden":false},"nteract":{"transient":{"deleting":false}}},"outputs":[],"source":[]}],"metadata":{"kernel_info":{"name":".net-csharp"},"kernelspec":{"display_name":".NET (C#)","language":"C#","name":".net-csharp"},"language_info":{"file_extension":".cs","mimetype":"text/x-csharp","name":"C#","pygments_lexer":"csharp","version":"8.0"},"nteract":{"version":"nteract-front-end@1.0.0"}},"nbformat":4,"nbformat_minor":2}