Notebook Version: 1.0
Platforms Supported:
Data Sources Required:
.Net Interactive installation is required! :
** About this notebook **:
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#.
Lastly, don't forget to install .Net Interactive to use this notebook!
// Try your .NET Interactive - C# kernel
Console.WriteLine("I am in C# land!")
// If you want to reference a library from Nuget
#r "nuget:Octokit, 0.32.0"
#r "nuget:NodaTime, 2.4.6"
using Octokit;
using NodaTime;
using NodaTime.Extensions;
using XPlot.Plotly;
// Get AAD access token using AZ CLI
#!pwsh
#Change the default colors
$Host.PrivateData.WarningBackgroundColor = "White"
$Host.PrivateData.WarningForegroundColor = "Black"
$accessPass = az account get-access-token
$passJson = $accessPass | ConvertFrom-Json
$accessToken = $passJson[0].accessToken
// Transfer $accessToken in PowerShell to C# variable
#!csharp
#!share --from pwsh accessToken
string token = accessToken;
// class to read Sentinel workspace configuration: config.json in the directory
using System.IO;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
public class SentinelConfiguration
{
public string TenantId { get; set; }
public string SubscriptionId { get; set; }
public string ResourceGroup { get; set; }
public string WorkspaceId { get; set; }
public string WorkspaceName { get; set; }
public SentinelConfiguration ReadConfiguration()
{
var config = new SentinelConfiguration();
using (StreamReader reader = new StreamReader("config.json"))
{
string json = reader.ReadToEnd();
var jsonObj = JObject.Parse(json);
config.TenantId = (string)jsonObj["tenant_id"];
config.SubscriptionId = (string)jsonObj["subscription_id"];
config.ResourceGroup = (string)jsonObj["resource_group"];
config.WorkspaceId = (string)jsonObj["workspace_id"];
config.WorkspaceName = (string)jsonObj["workspace_name"];
}
return config;
}
}
// Define a class as Azure REST API Helper
using System.Net.Http;
public class AzureResourceApiHelper
{
public const string BaseUrl = "https://management.azure.com";
public string AccessTokenTemplate = "Bearer {0}";
public string BuildResourceUrl(string azureResourceId)
{
return BaseUrl + azureResourceId;
}
public HttpResponseMessage HttpGet(string token, string url)
{
HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", token);
HttpResponseMessage response = client.GetAsync(url).GetAwaiter().GetResult();
return response;
}
}
// Derfine a C# class for Azure Sentinel Watchlist
public class SentinelWatchlist
{
private string watchlistsTemplate = "/subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.OperationalInsights/workspaces/{2}/providers/Microsoft.SecurityInsights/watchlists?api-version=2019-01-01-preview";
private string watchlistTemplate = "/subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.OperationalInsights/workspaces/{2}/providers/Microsoft.SecurityInsights/watchlists/{3}?api-version=2019-01-01-preview";
// Get the watchlist by watchlist alias
public HttpResponseMessage GetWatchlist(string accessToken, string watchlistAlias)
{
// Read config
SentinelConfiguration config = new SentinelConfiguration();
config = config.ReadConfiguration();
// call API
AzureResourceApiHelper helper = new AzureResourceApiHelper();
string resourceId = string.Format(watchlistTemplate, config.SubscriptionId, config.ResourceGroup,config.WorkspaceName, watchlistAlias);
string url = helper.BuildResourceUrl(resourceId);
string token = string.Format(helper.AccessTokenTemplate, accessToken);
return helper.HttpGet(token, url);
}
// Get all watchlists
public HttpResponseMessage GetAllWatchlists(string accessToken)
{
// Read config
SentinelConfiguration config = new SentinelConfiguration();
config = config.ReadConfiguration();
// call API
AzureResourceApiHelper helper = new AzureResourceApiHelper();
string resourceId = string.Format(watchlistsTemplate, config.SubscriptionId, config.ResourceGroup,config.WorkspaceName);
string url = helper.BuildResourceUrl(resourceId);
string token = string.Format(helper.AccessTokenTemplate, accessToken);
return helper.HttpGet(token, url);
}
}
// Utils class
using System.Text.Json;
using Microsoft.AspNetCore.Html;
public class Utils
{
// Format json for readability
public static string PrettyJson(string rawJson)
{
var options = new JsonSerializerOptions()
{
WriteIndented = true
};
var jsonElement = System.Text.Json.JsonSerializer.Deserialize<JsonElement>(rawJson);
return System.Text.Json.JsonSerializer.Serialize(jsonElement, options);
}
public static void TableDisplay()
{
Microsoft.DotNet.Interactive.Formatting.Formatter.Register<Dictionary<int, string>>((dict, writter) =>
{
var headers = new List<IHtmlContent>();
headers.Add(th("Watchlist Alias"));
headers.Add(th("Updated Date"));
var rows = new List<List<IHtmlContent>>();
foreach (var pair in dict)
{
var cells = new List<IHtmlContent>();
cells.Add(td(pair.Key));
cells.Add(td(pair.Value));
rows.Add(cells);
}
var t = table(
thead(headers),
tbody(rows.Select(r => tr(r)))
);
writter.Write(t);
}, "text/html");
}
}
// Get all watchlists, display alias
var wl = new SentinelWatchlist();
var responseMsg = wl.GetAllWatchlists(token);
string content = responseMsg.Content.ReadAsStringAsync().GetAwaiter().GetResult();
//Console.WriteLine(content);
dynamic x = Newtonsoft.Json.JsonConvert.DeserializeObject(content);
var allLists = x.value;
int index = 0;
var allWatchlist = new Dictionary<string, string>();
foreach(var watchlist in allLists)
{
allWatchlist.Add(watchlist.properties.watchlistAlias.ToString(), watchlist.properties.updated.ToString());
}
// Display data in HTML table
Utils.TableDisplay();
allWatchlist
// if you have watchlist, then you may get a specific watchlist
if (allLists.Count > 0)
{
// I set the index = 0, but you may select any index that is in the range of index
var wlAlias = allWatchlist.Keys.FirstOrDefault();
var responseMsg = wl.GetWatchlist(token, wlAlias);
string content = responseMsg.Content.ReadAsStringAsync().GetAwaiter().GetResult();
Console.WriteLine(Utils.PrettyJson(content));
}