Compare commits
14 Commits
e0189381f1
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| 5cad97c9ac | |||
| cc61b02959 | |||
| 0dfe68656d | |||
| 6544dc5a3d | |||
| 08e518c340 | |||
| e82d198ee7 | |||
| 4c6a9e6dec | |||
| feb1326cee | |||
| 626ab99888 | |||
| 9c8189bc33 | |||
| 956aa8b3b0 | |||
| 7d5b2a7aac | |||
| 5f089fb01f | |||
| af3cc81180 |
@@ -1,8 +1,8 @@
|
|||||||
using AS1024.GeoFeed.Core.Interfaces;
|
using AS1024.GeoFeed.Core.Interfaces;
|
||||||
|
using AS1024.GeoFeed.Core.Tools;
|
||||||
using AS1024.GeoFeed.Models;
|
using AS1024.GeoFeed.Models;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.Extensions.Hosting;
|
using Microsoft.Extensions.Hosting;
|
||||||
using AS1024.GeoFeed.Core.Tools;
|
|
||||||
|
|
||||||
namespace AS1024.GeoFeed.Core.GeoFeedSqliteLocalCache
|
namespace AS1024.GeoFeed.Core.GeoFeedSqliteLocalCache
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,14 +1,16 @@
|
|||||||
using System.Text;
|
using AS1024.GeoFeed.Core.Interfaces;
|
||||||
using AS1024.GeoFeed.Core.Interfaces;
|
|
||||||
using AS1024.GeoFeed.Core.Tools;
|
using AS1024.GeoFeed.Core.Tools;
|
||||||
using AS1024.GeoFeed.Models;
|
using AS1024.GeoFeed.Models;
|
||||||
using Microsoft.Extensions.Caching.Memory;
|
using Microsoft.Extensions.Caching.Memory;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
namespace AS1024.GeoFeed.Core.WebLogic
|
namespace AS1024.GeoFeed.Core.WebLogic
|
||||||
{
|
{
|
||||||
public class GeoFeedReturn
|
public class GeoFeedReturn
|
||||||
{
|
{
|
||||||
private const string GeoFeedCacheKey = "GeoFeedData";
|
private const string GeoFeedCacheKey = "GeoFeedData";
|
||||||
|
private const string GeoFeedMimeTypeReturn = "text/csv";
|
||||||
|
private const string GeoFeedFileName = "geofeed.csv";
|
||||||
private readonly IGeoFeedProvider provider;
|
private readonly IGeoFeedProvider provider;
|
||||||
private readonly ILogger<GeoFeedReturn> logger;
|
private readonly ILogger<GeoFeedReturn> logger;
|
||||||
private readonly IGeoFeedPersistentCacheProvider cacheProvider;
|
private readonly IGeoFeedPersistentCacheProvider cacheProvider;
|
||||||
@@ -46,8 +48,8 @@ namespace AS1024.GeoFeed.Core.WebLogic
|
|||||||
}
|
}
|
||||||
|
|
||||||
return Results.File(Encoding.UTF8.GetBytes(feed.ToGeoFeedCsv(true, isCached)),
|
return Results.File(Encoding.UTF8.GetBytes(feed.ToGeoFeedCsv(true, isCached)),
|
||||||
"text/csv",
|
GeoFeedMimeTypeReturn,
|
||||||
"geofeed.csv");
|
GeoFeedFileName);
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (HttpRequestException ex)
|
catch (HttpRequestException ex)
|
||||||
@@ -56,8 +58,8 @@ namespace AS1024.GeoFeed.Core.WebLogic
|
|||||||
string geoFeedData = cacheProvider.GetGeoFeed();
|
string geoFeedData = cacheProvider.GetGeoFeed();
|
||||||
|
|
||||||
return Results.File(Encoding.UTF8.GetBytes(geoFeedData),
|
return Results.File(Encoding.UTF8.GetBytes(geoFeedData),
|
||||||
"text/csv",
|
GeoFeedMimeTypeReturn,
|
||||||
"geofeed.csv");
|
GeoFeedFileName);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,13 +1,7 @@
|
|||||||
using AS1024.GeoFeed.Core.Interfaces;
|
using AS1024.GeoFeed.Core.Interfaces;
|
||||||
using AS1024.GeoFeed.Models;
|
|
||||||
using AS1024.GeoFeed.Core.Tools;
|
using AS1024.GeoFeed.Core.Tools;
|
||||||
|
using AS1024.GeoFeed.Models;
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
using Microsoft.Extensions.Hosting;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
namespace AS1024.GeoFeed.Core.CacheService
|
namespace AS1024.GeoFeed.Core.CacheService
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
using AS1024.GeoFeed.Core.Interfaces;
|
using AS1024.GeoFeed.Core.Interfaces;
|
||||||
using AS1024.GeoFeed.Models;
|
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.Configuration;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
using System.Net.Http.Headers;
|
||||||
|
using System.Net.Sockets;
|
||||||
|
using System.Text.Json;
|
||||||
|
using System.Web;
|
||||||
|
|
||||||
namespace AS1024.GeoFeed.Core.GeoFeedProviders
|
namespace AS1024.GeoFeed.Core.GeoFeedProviders
|
||||||
{
|
{
|
||||||
@@ -52,7 +52,7 @@ namespace AS1024.GeoFeed.Core.GeoFeedProviders
|
|||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
string stringResult = await result.Content.ReadAsStringAsync();
|
var stringResult = await result.Content.ReadAsStreamAsync();
|
||||||
jsonData = DeserializeJsonData(stringResult);
|
jsonData = DeserializeJsonData(stringResult);
|
||||||
|
|
||||||
if (jsonData?.Results == null || jsonData.Results.Count == 0)
|
if (jsonData?.Results == null || jsonData.Results.Count == 0)
|
||||||
@@ -93,7 +93,7 @@ namespace AS1024.GeoFeed.Core.GeoFeedProviders
|
|||||||
return geoFeed;
|
return geoFeed;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual NetboxData? DeserializeJsonData(string stringResult)
|
protected virtual NetboxData? DeserializeJsonData(Stream stringResult)
|
||||||
{
|
{
|
||||||
return JsonSerializer.Deserialize<NetboxData>(stringResult, new JsonSerializerOptions
|
return JsonSerializer.Deserialize<NetboxData>(stringResult, new JsonSerializerOptions
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,9 +1,4 @@
|
|||||||
using AS1024.GeoFeed.Models;
|
using AS1024.GeoFeed.Models;
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace AS1024.GeoFeed.Core.Interfaces
|
namespace AS1024.GeoFeed.Core.Interfaces
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -6,25 +6,31 @@ namespace AS1024.GeoFeed.Core.Tools
|
|||||||
public static class GeoFeedTools
|
public static class GeoFeedTools
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns a CSV string for a given GeoFeed retreived from various sources
|
/// Returns a CSV string for a given GeoFeed retrieved from various sources.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="geoFeeds">GeoFeed returned from the source of truth</param>
|
/// <param name="geoFeeds">GeoFeed returned from the source of truth.</param>
|
||||||
/// <param name="timeStamp">If a timestamp should be appended at the header</param>
|
/// <param name="timeStamp">If a timestamp should be appended at the header.</param>
|
||||||
/// <param name="isCached">If the result is cached</param>
|
/// <param name="isCached">If the result is cached.</param>
|
||||||
/// <returns></returns>
|
/// <returns>CSV formatted string of GeoFeed data.</returns>
|
||||||
public static string ToGeoFeedCsv(this List<IPGeoFeed> geoFeeds, bool timeStamp = false, bool isCached = false)
|
public static string ToGeoFeedCsv(this List<IPGeoFeed> geoFeeds, bool timeStamp = false, bool isCached = false)
|
||||||
{
|
{
|
||||||
|
if (geoFeeds == null) throw new ArgumentNullException(nameof(geoFeeds));
|
||||||
|
|
||||||
StringBuilder csvContent = new();
|
StringBuilder csvContent = new();
|
||||||
|
|
||||||
|
// Append timestamp header if required
|
||||||
if (timeStamp)
|
if (timeStamp)
|
||||||
csvContent.AppendLine($"# GeoFeed generated on {DateTime.UtcNow:R}");
|
csvContent.AppendFormat("# GeoFeed generated on {0:R}\n", DateTime.UtcNow);
|
||||||
|
|
||||||
|
// Append cache status if required
|
||||||
if (isCached)
|
if (isCached)
|
||||||
csvContent.AppendLine($"# Geofeed data is returned from local in memory cache");
|
csvContent.AppendLine("# Geofeed data is returned from local in memory cache");
|
||||||
|
|
||||||
|
// Iterate over each GeoFeed entry to append its details to the CSV content
|
||||||
foreach (IPGeoFeed feed in geoFeeds)
|
foreach (IPGeoFeed feed in geoFeeds)
|
||||||
{
|
{
|
||||||
csvContent.AppendLine($"{feed.Prefix},{feed.GeolocCountry},{feed.GeolocRegion},{feed.GeolocCity},{feed.GeolocPostalCode}");
|
// Using AppendFormat for a cleaner and more readable approach to constructing CSV lines
|
||||||
|
csvContent.AppendFormat("{0},{1},{2},{3},{4}\n", feed.Prefix, feed.GeolocCountry, feed.GeolocRegion, feed.GeolocCity, feed.GeolocPostalCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
return csvContent.ToString();
|
return csvContent.ToString();
|
||||||
|
|||||||
24
AS1024.GeoFeed.MinimalAPI/Dockerfile.bare-image
Normal file
24
AS1024.GeoFeed.MinimalAPI/Dockerfile.bare-image
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
#See https://aka.ms/customizecontainer to learn how to customize your debug container and how Visual Studio uses this Dockerfile to build your images for faster debugging.
|
||||||
|
|
||||||
|
FROM mcr.microsoft.com/dotnet/sdk:8.0-alpine AS build
|
||||||
|
# Install clang/zlib1g-dev dependencies for publishing to native
|
||||||
|
RUN apk add clang zlib-static zlib-dev musl-dev libc6-compat cmake autoconf make openssl-dev openssl-libs-static icu-static icu-dev
|
||||||
|
ARG BUILD_CONFIGURATION=Release
|
||||||
|
WORKDIR /src
|
||||||
|
COPY ["AS1024.GeoFeed.MinimalAPI/AS1024.GeoFeed.MinimalAPI.csproj", "AS1024.GeoFeed.MinimalAPI/"]
|
||||||
|
RUN dotnet restore "./AS1024.GeoFeed.MinimalAPI/./AS1024.GeoFeed.MinimalAPI.csproj"
|
||||||
|
COPY . .
|
||||||
|
WORKDIR "/src/AS1024.GeoFeed.MinimalAPI"
|
||||||
|
RUN dotnet build "./AS1024.GeoFeed.MinimalAPI.csproj" -c $BUILD_CONFIGURATION -o /app/build
|
||||||
|
|
||||||
|
FROM build AS publish
|
||||||
|
ARG BUILD_CONFIGURATION=Release
|
||||||
|
RUN dotnet publish "./AS1024.GeoFeed.MinimalAPI.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:StaticOpenSslLinking=true /p:StaticExecutable=true /p:StaticallyLinked=true /p:StripSymbols=true /p:DebugType=None /p:DebugSymbols=false
|
||||||
|
|
||||||
|
FROM scratch AS final
|
||||||
|
WORKDIR /tmp
|
||||||
|
WORKDIR /app
|
||||||
|
EXPOSE 8080
|
||||||
|
COPY --from=publish /app/publish .
|
||||||
|
COPY --from=build /etc/ssl/certs/* /etc/ssl/certs/
|
||||||
|
ENTRYPOINT ["./AS1024.GeoFeed.MinimalAPI"]
|
||||||
@@ -14,7 +14,7 @@ namespace AS1024.GeoFeed.MinimalAPI
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override NetboxData? DeserializeJsonData(string stringResult)
|
protected override NetboxData? DeserializeJsonData(Stream stringResult)
|
||||||
{
|
{
|
||||||
return JsonSerializer.Deserialize(stringResult, AppJsonSerializerContext.Default.NetboxData);
|
return JsonSerializer.Deserialize(stringResult, AppJsonSerializerContext.Default.NetboxData);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,16 +19,19 @@ namespace AS1024.GeoFeed.MinimalAPI
|
|||||||
builder.Services.AddMemoryCache();
|
builder.Services.AddMemoryCache();
|
||||||
builder.Services.AddLogging();
|
builder.Services.AddLogging();
|
||||||
builder.Services.AddHttpClient();
|
builder.Services.AddHttpClient();
|
||||||
builder.Services.ConfigureHttpJsonOptions(options => {
|
builder.Services.ConfigureHttpJsonOptions(options =>
|
||||||
|
{
|
||||||
options.SerializerOptions.TypeInfoResolverChain.Insert(0, AppJsonSerializerContext.Default);
|
options.SerializerOptions.TypeInfoResolverChain.Insert(0, AppJsonSerializerContext.Default);
|
||||||
});
|
});
|
||||||
var app = builder.Build();
|
var app = builder.Build();
|
||||||
|
|
||||||
app.Map("/geofeed.csv", async (GeoFeedReturn feedReturn) => {
|
app.Map("/geofeed.csv", async (GeoFeedReturn feedReturn) =>
|
||||||
|
{
|
||||||
return await feedReturn.GetGeoFeed();
|
return await feedReturn.GetGeoFeed();
|
||||||
});
|
});
|
||||||
|
|
||||||
app.Map("/geofeed", async (GeoFeedReturn feedReturn) => {
|
app.Map("/geofeed", async (GeoFeedReturn feedReturn) =>
|
||||||
|
{
|
||||||
return await feedReturn.GetGeoFeed();
|
return await feedReturn.GetGeoFeed();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
using System.Text.Json.Serialization;
|
namespace AS1024.GeoFeed.Models
|
||||||
namespace AS1024.GeoFeed.Models
|
|
||||||
{
|
{
|
||||||
public class NetboxData
|
public class NetboxData
|
||||||
{
|
{
|
||||||
public List<Result>? Results { get; set; }
|
public List<Result>? Results { get; set; }
|
||||||
public string? Next { get; set; }
|
public string? Next { get; set; }
|
||||||
public string? Previous { get; set; }
|
public string? Previous { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Result
|
public class Result
|
||||||
@@ -41,7 +40,8 @@ namespace AS1024.GeoFeed.Models
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// This class represents the IP GeoFeed Entry
|
/// This class represents the IP GeoFeed Entry
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class IPGeoFeed : CustomFields {
|
public class IPGeoFeed : CustomFields
|
||||||
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents the IP Prefix for the associated GeoFeed entry
|
/// Represents the IP Prefix for the associated GeoFeed entry
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
using Microsoft.AspNetCore.Mvc;
|
using AS1024.GeoFeed.Core.WebLogic;
|
||||||
using AS1024.GeoFeed.Core.WebLogic;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
|
||||||
namespace AS1024.GeoFeed.Controllers
|
namespace AS1024.GeoFeed.Controllers
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
using AS1024.GeoFeed.Core.Interfaces;
|
using AS1024.GeoFeed.Core.CacheService;
|
||||||
using AS1024.GeoFeed.Core.GeoFeedPreloader;
|
using AS1024.GeoFeed.Core.GeoFeedPreloader;
|
||||||
using AS1024.GeoFeed.Core.GeoFeedProviders;
|
using AS1024.GeoFeed.Core.GeoFeedProviders;
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using AS1024.GeoFeed.Core.GeoFeedSqliteLocalCache;
|
using AS1024.GeoFeed.Core.GeoFeedSqliteLocalCache;
|
||||||
using AS1024.GeoFeed.Core.CacheService;
|
using AS1024.GeoFeed.Core.Interfaces;
|
||||||
using AS1024.GeoFeed.Core.WebLogic;
|
using AS1024.GeoFeed.Core.WebLogic;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
namespace AS1024.GeoFeed
|
namespace AS1024.GeoFeed
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -109,6 +109,8 @@ The application provides the following key endpoints:
|
|||||||
|
|
||||||
This application is designed to always communicate over HTTPS with NetBox, ensuring that the data transfer is encrypted and secure.
|
This application is designed to always communicate over HTTPS with NetBox, ensuring that the data transfer is encrypted and secure.
|
||||||
|
|
||||||
---
|
## Extending Beyond NetBox
|
||||||
|
|
||||||
For more information about configuring and using this application, please refer to the official .NET documentation and the NetBox API guide.
|
If your current IPAM solution is not netbox and wish to extend this web application to use the desired IPAM solution of choice, the interface `IGeoFeedProvider` is available for extensibility. To use your custom IPAM backend ensure that `NetboxAoTGeoFeedProvider` and `NetboxGeoFeedProvider` are not registered in the dependency injection container in the Web Apps. Once unregistered, register your custom IPAM communication backend provider to your needs and the web app should work in both AOT and MVC mode.
|
||||||
|
|
||||||
|
Currently the Minimal API implementation of this web application only supports code that does not require reflection. This is a known limitation of native AOT deployments. If your code utilizes reflection or is not properly adapted for source generation, the minimal API version will **not work**.
|
||||||
14
docker/Caddyfile
Normal file
14
docker/Caddyfile
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
{$GEOFEEDDOMAIN}:443 {
|
||||||
|
log {
|
||||||
|
level INFO
|
||||||
|
output file {$LOG_FILE} {
|
||||||
|
roll_size 10MB
|
||||||
|
roll_keep 10
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Use the ACME HTTP-01 challenge to get a cert for the configured domain.
|
||||||
|
tls {$EMAIL}
|
||||||
|
|
||||||
|
reverse_proxy geofeed:8080
|
||||||
|
}
|
||||||
28
docker/docker-compose.yml
Normal file
28
docker/docker-compose.yml
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
version: '3.7'
|
||||||
|
services:
|
||||||
|
geofeed:
|
||||||
|
# use the image tag aot-minimal for the AOT version for fastest startup performance
|
||||||
|
image: git.startmywifi.com/as1024/geofeed:latest
|
||||||
|
restart: always
|
||||||
|
volumes:
|
||||||
|
- './data:/data'
|
||||||
|
environment:
|
||||||
|
- ASPNETCORE_URLS=http://+:8080
|
||||||
|
- ConnectionString__LocalFeedCache=Data Source=/data/geofeed-cache.db
|
||||||
|
- APIKey=APIKeyHere
|
||||||
|
- NetBoxHost=netboxhosthere
|
||||||
|
caddy:
|
||||||
|
image: caddy:2
|
||||||
|
restart: always
|
||||||
|
ports:
|
||||||
|
- 80:80
|
||||||
|
- 443:443
|
||||||
|
- 443:443/udp
|
||||||
|
volumes:
|
||||||
|
- ./Caddyfile:/etc/caddy/Caddyfile:ro
|
||||||
|
- ./caddy-config:/config
|
||||||
|
- ./caddy-data:/data
|
||||||
|
environment:
|
||||||
|
GEOFEEDDOMAIN: "https://geofeed.exampleas.net"
|
||||||
|
EMAIL: "noc@example.com" # The email address to use for ACME registration.
|
||||||
|
LOG_FILE: "/data/access.log"
|
||||||
Reference in New Issue
Block a user