using AS1024.GeoFeed.Core.Interfaces; using AS1024.GeoFeed.Models; using System.Text.Json; using System.Net.Http.Headers; using System.Net.Sockets; using System.Web; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; namespace AS1024.GeoFeed.Core.GeoFeedProviders { public abstract class NetBoxGeoFeedProviderBase : IGeoFeedProvider { protected readonly IConfiguration configuration; protected readonly ILogger logger; protected readonly IList addressFamilies = new List() { AddressFamily.InterNetwork, AddressFamily.InterNetworkV6 }; protected readonly IHttpClientFactory httpClientFactory; string IGeoFeedProvider.GeoFeedProviderName => "netbox"; public NetBoxGeoFeedProviderBase(IConfiguration configuration, ILogger logger, IHttpClientFactory httpClientFactory) { this.configuration = configuration; this.logger = logger; this.httpClientFactory = httpClientFactory; } public async Task> GetGeoFeedDataAsync() { List geoFeed = []; using HttpClient client = httpClientFactory.CreateClient(); client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Token", configuration["APIKey"]); client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); foreach (AddressFamily family in addressFamilies) { Uri uri = BuildNetBoxURI(family); NetboxData? jsonData = null; while (true) { logger.LogDebug($"Making request to {uri}..."); using HttpResponseMessage result = await client.GetAsync(uri); if (!result.IsSuccessStatusCode) { break; } string stringResult = await result.Content.ReadAsStringAsync(); jsonData = DeserializeJsonData(stringResult); if (jsonData?.Results == null || jsonData.Results.Count == 0) { break; } foreach (Result data in jsonData.Results) { try { geoFeed.Add(new IPGeoFeed { Prefix = data.Prefix, GeolocCity = data.CustomFields.GeolocCity, GeolocRegion = data.CustomFields.GeolocRegion, GeolocCountry = data.CustomFields.GeolocCountry, GeolocHasLocation = data.CustomFields.GeolocHasLocation, GeolocPostalCode = data.CustomFields.GeolocPostalCode }); } catch (Exception ex) { logger.LogError(ex.ToString()); } } if (!string.IsNullOrEmpty(jsonData.Next)) { uri = new Uri(jsonData.Next); continue; } break; } } return geoFeed; } protected virtual NetboxData? DeserializeJsonData(string stringResult) { return JsonSerializer.Deserialize(stringResult, new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower }); } protected Uri BuildNetBoxURI(AddressFamily family) { System.Collections.Specialized.NameValueCollection queryParameters = HttpUtility.ParseQueryString(string.Empty); queryParameters["cf_geoloc_has_location"] = "true"; queryParameters["limit"] = "50"; switch (family) { case AddressFamily.InterNetwork: queryParameters["mask_length__lte"] = "24"; queryParameters["family"] = "4"; break; case AddressFamily.InterNetworkV6: queryParameters["mask_length__lte"] = "48"; queryParameters["family"] = "6"; break; } UriBuilder endUrl = new UriBuilder { Path = "api/ipam/prefixes/", Query = queryParameters.ToString(), Host = configuration["NetBoxHost"], Scheme = "https" }; return endUrl.Uri; } } }