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");
        }
Example #2
0
        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"));
        }