GeoFeed/AS1024.GeoFeed.Core/GeoFeedProviders/NetBoxGeoFeedProviderBase.cs

135 lines
4.9 KiB
C#

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<NetBoxGeoFeedProvider> logger;
protected readonly IList<AddressFamily> addressFamilies = new List<AddressFamily>()
{
AddressFamily.InterNetwork,
AddressFamily.InterNetworkV6
};
protected readonly IHttpClientFactory httpClientFactory;
string IGeoFeedProvider.GeoFeedProviderName => "netbox";
public NetBoxGeoFeedProviderBase(IConfiguration configuration,
ILogger<NetBoxGeoFeedProvider> logger,
IHttpClientFactory httpClientFactory)
{
this.configuration = configuration;
this.logger = logger;
this.httpClientFactory = httpClientFactory;
}
public async Task<List<IPGeoFeed>> GetGeoFeedData()
{
List<IPGeoFeed> 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<NetboxData>(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;
}
}
}