public static async Task Run([HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequest req, TraceWriter log) { log.Info("C# HTTP trigger function processed a request."); //Parse alert request string requestBody = new StreamReader(req.Body).ReadToEnd(); Webhook data = new Webhook(); data = JsonConvert.DeserializeObject <Webhook>(requestBody); Context alertResource = data.RequestBody.context; IConfigurationRoot config = new ConfigurationBuilder() .AddJsonFile("local.settings.json", optional: true, reloadOnChange: true) .AddEnvironmentVariables() .Build(); string tenantId = config.GetConnectionString("TenantId"); string clientId = config.GetConnectionString("clientId"); string clientKey = config.GetConnectionString("ClientKey"); if (string.IsNullOrEmpty(tenantId) || string.IsNullOrEmpty(clientId) || string.IsNullOrEmpty(clientKey)) { log.Error("Serivice credentials are null. Check connection string settings"); return; } AzureCredentials credentials = SdkContext.AzureCredentialsFactory.FromServicePrincipal(clientId, clientKey, tenantId, AzureEnvironment.AzureGlobalCloud); IAzure azure = Azure.Configure().Authenticate(credentials).WithSubscription(alertResource.subscriptionId); if (azure == null) { log.Error("Error: Issues logging into Azure subscription: " + alertResource.subscriptionId + ". Exiting."); return; } IVirtualMachine VM = await azure.VirtualMachines.GetByIdAsync(alertResource.resourceId); if (VM == null) { log.Error("Error: VM: " + alertResource.resourceId + "was not found. Exiting."); return; } INetworkWatcher networkWatcher = await EnsureNetworkWatcherExists(azure, VM.Region, log); InstallNetworkWatcherExtension(VM, log); string storageAccountId = Environment.GetEnvironmentVariable("PacketCaptureStorageAccount"); var storageAccount = await azure.StorageAccounts.GetByIdAsync(storageAccountId); if (storageAccount == null) { log.Error("Storage Account: " + storageAccountId + " not found. Exiting."); return; } string packetCaptureName = VM.Name.Substring(0, System.Math.Min(63, VM.Name.Length)) + System.DateTime.Now.ToString("s").Replace(":", ""); IPacketCaptures packetCapturesObj = networkWatcher.PacketCaptures; var packetCaptures = packetCapturesObj.List().ToList(); if (packetCaptures.Count >= 10) { log.Info("More than 10 Captures, finding oldest."); var packetCaptureTasks = new List <Task <IPacketCaptureStatus> >(); foreach (IPacketCapture pcap in packetCaptures) { packetCaptureTasks.Add(pcap.GetStatusAsync()); } var packetCaptureStatuses = new List <Tuple <IPacketCapture, IPacketCaptureStatus> >(); for (int i = 0; i < packetCaptureTasks.Count; ++i) { packetCaptureStatuses.Add(new Tuple <IPacketCapture, IPacketCaptureStatus>(packetCaptures[i], await packetCaptureTasks[i])); } packetCaptureStatuses.Sort((Tuple <IPacketCapture, IPacketCaptureStatus> first, Tuple <IPacketCapture, IPacketCaptureStatus> second) => { return(first.Item2.CaptureStartTime.CompareTo(second.Item2.CaptureStartTime)); }); log.Info("Removing: " + packetCaptureStatuses.First().Item1.Name); await networkWatcher.PacketCaptures.DeleteByNameAsync(packetCaptureStatuses.First().Item1.Name); } log.Info("Creating Packet Capture"); await networkWatcher.PacketCaptures .Define(packetCaptureName) .WithTarget(VM.Id) .WithStorageAccountId(storageAccount.Id) .WithTimeLimitInSeconds(15) .CreateAsync(); log.Info("Packet Capture created successfully"); }
public static async Task <HttpResponseMessage> Run([HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequestMessage req, TraceWriter log) { try { log.Info("C# HTTP trigger function processed a request."); //Parse alert request log.Verbose($"Parsing Alert Request..."); string requestBody = req.Content.ReadAsStringAsync().Result; dynamic contextData = JObject.Parse(requestBody).SelectToken("$..context"); string curSubscriptionId = contextData?.subscriptionId; string curResourceGroupName = contextData?.resourceGroupName; string curResourceRegion = contextData?.resourceRegion; string curResourceName = contextData?.resourceName; string curResourceId = contextData?.resourceId; string displayContext = $"SubscriptionID: { curSubscriptionId}\nResourceGroupName: { curResourceGroupName} \nResourceRegion: { curResourceRegion} \nResourceName: { curResourceName} \nResourceId: { curResourceId}"; if ( (curSubscriptionId == null) || (curResourceGroupName == null) || (curResourceRegion == null) || (curResourceName == null) || (curResourceId == null)) { string errorString = $"Insufficient context sent by webhook: \n{displayContext}"; log.Error(errorString); return(req.CreateResponse(HttpStatusCode.BadRequest, errorString)); } log.Verbose($"Context from webhook parsed: \n{displayContext}"); log.Verbose($"Getting Configuration"); string tenantId = System.Configuration.ConfigurationManager.ConnectionStrings["TenantId"].ConnectionString; string clientId = System.Configuration.ConfigurationManager.ConnectionStrings["clientId"].ConnectionString; string clientKey = System.Configuration.ConfigurationManager.ConnectionStrings["ClientKey"].ConnectionString; if (string.IsNullOrEmpty(tenantId) || string.IsNullOrEmpty(clientId) || string.IsNullOrEmpty(clientKey)) { string errorString = "Service credentials are null. Check connection string settings"; log.Error(errorString); return(req.CreateResponse(HttpStatusCode.InternalServerError, errorString)); } log.Verbose($"Getting Credentials"); AzureCredentials credentials = SdkContext.AzureCredentialsFactory.FromServicePrincipal(clientId, clientKey, tenantId, AzureEnvironment.AzureGlobalCloud); IAzure azure = Azure.Configure().Authenticate(credentials).WithSubscription(curSubscriptionId); if (azure == null) { string errorString = $"Error: Issues logging into Azure subscription: {curSubscriptionId}. Exiting."; log.Error(errorString); return(req.CreateResponse(HttpStatusCode.InternalServerError, errorString)); } log.Verbose("Azure Credentials successfully created"); log.Verbose("Obtaining VM"); IVirtualMachine VM = await azure.VirtualMachines.GetByIdAsync(curResourceId); if (VM == null) { string errorString = $"Error: VM: {curResourceId} was not found. Exiting."; log.Error(errorString); return(req.CreateResponse(HttpStatusCode.BadRequest, errorString)); } log.Verbose($"VM found: {curResourceName}; {curResourceId}"); log.Verbose($"Checking for Network Watcher in region: {VM.Region}"); INetworkWatcher networkWatcher; try { networkWatcher = await EnsureNetworkWatcherExists(azure, VM.Region, log); } catch (Exception err) { string errorString = $"Error confirming network watcher. {err.ToString()}."; log.Error(errorString); return(req.CreateResponse(HttpStatusCode.InternalServerError, errorString)); } log.Verbose($"Checking for Network Watcher Extension on VM: {VM.Name}"); InstallNetworkWatcherExtension(VM, log); log.Verbose("Looking for Storage Account"); string storageAccountId = Environment.GetEnvironmentVariable("PacketCaptureStorageAccount"); var storageAccount = await azure.StorageAccounts.GetByIdAsync(storageAccountId); if (storageAccount == null) { string errorString = $"PCAP Storage Account: {storageAccountId} not found. Exiting."; log.Error(errorString); return(req.CreateResponse(HttpStatusCode.InternalServerError, errorString)); } log.Verbose("Storage Account found"); string packetCaptureName = VM.Name.Substring(0, System.Math.Min(50, VM.Name.Length)) + System.DateTime.Now.ToString("yyyyMMddhhmmss").Replace(":", ""); log.Verbose($"Packet Capture Name: {packetCaptureName}"); try { IPacketCaptures packetCapturesObj = networkWatcher.PacketCaptures; var packetCaptures = packetCapturesObj.List().ToList(); if (packetCaptures.Count >= 5) { log.Info("More than 10 Captures, finding oldest."); var packetCaptureTasks = new List <Task <IPacketCaptureStatus> >(); foreach (IPacketCapture pcap in packetCaptures) { packetCaptureTasks.Add(pcap.GetStatusAsync()); } var packetCaptureStatuses = new List <Tuple <IPacketCapture, IPacketCaptureStatus> >(); for (int i = 0; i < packetCaptureTasks.Count; ++i) { packetCaptureStatuses.Add(new Tuple <IPacketCapture, IPacketCaptureStatus>(packetCaptures[i], await packetCaptureTasks[i])); } packetCaptureStatuses.Sort((Tuple <IPacketCapture, IPacketCaptureStatus> first, Tuple <IPacketCapture, IPacketCaptureStatus> second) => { return(first.Item2.CaptureStartTime.CompareTo(second.Item2.CaptureStartTime)); }); log.Info("Removing: " + packetCaptureStatuses.First().Item1.Name); networkWatcher.PacketCaptures.DeleteByNameAsync(packetCaptureStatuses.First().Item1.Name); } } catch (Exception delErr) { log.Error($"Error when deleting existing packet capture. Attempting to continue.... {delErr.ToString()}"); } log.Info("Creating Packet Capture"); await networkWatcher.PacketCaptures .Define(packetCaptureName) .WithTarget(VM.Id) .WithStorageAccountId(storageAccount.Id) .WithTimeLimitInSeconds(15) .CreateAsync(); log.Info("Packet Capture created successfully"); } catch (Exception err) { string unhandledErrString = $"Function Ending: error in AlertPacketCapture: {err.ToString()}"; log.Error(unhandledErrString); return(req.CreateResponse(HttpStatusCode.InternalServerError, unhandledErrString)); } return(req.CreateResponse(HttpStatusCode.OK, "PCAP Created")); }