Compare commits

..

31 Commits

Author SHA1 Message Date
48a1d6f984 Migrate to json deserializer 2024-01-11 16:18:39 -08:00
79090e91d6 Remove newtonsoft reference 2024-01-11 16:12:55 -08:00
7d2d27c609 Add docker support 2024-01-11 16:10:52 -08:00
c32f3596ec Update launch settings 2024-01-11 16:10:42 -08:00
1fd587634b Add initial docker support 2024-01-11 16:10:17 -08:00
4c17c375ae Remove NewtonSoft Json depedency 2024-01-08 23:45:16 -08:00
bf38c7dc1a Move away from NewtonSoft.Json 2024-01-08 23:28:35 -08:00
afb2102702 Upgrade to .NET 8.0 2024-01-08 22:03:15 -08:00
9c80ad14f3 Update code to properly format the AS Tags 2023-06-14 13:07:02 -07:00
7b6794e7e9 Change from Forbid to NotFound 2023-01-08 15:39:00 -08:00
e3f093b53a Mark types explicitly 2023-01-08 15:35:19 -08:00
5f18fe037c Update the readme file 2023-01-08 15:32:07 -08:00
ab2793d92a Return 403 instead of the view if we can’t get a response out of netbox 2023-01-08 15:07:13 -08:00
9fdc60ac48 Remove unused code 2023-01-08 13:38:47 -08:00
bd8198be2a Unify the strurcture 2023-01-08 13:37:30 -08:00
77e6235b30 Upgrade to .NET 7.0 2023-01-08 13:37:27 -08:00
fc432698a8 Add trailing slash for API endpoint 2023-01-08 13:37:23 -08:00
db29ac0891 Set response cache to an hour 2023-01-08 13:37:19 -08:00
672e56d0aa More cleanup 2023-01-08 13:37:17 -08:00
9311ba2b59 Fix the names 2023-01-08 13:37:15 -08:00
dbccb586f8 Remove unecessary usings 2023-01-08 13:36:46 -08:00
58576796c2 Clean up unused code 2023-01-08 13:36:44 -08:00
1a3450f6f9 Baby steps on code refactoring 2023-01-08 13:36:39 -08:00
1ee556eb4e Add an option to configure the netbox host 2022-12-13 09:16:59 -08:00
159bbf399c Mark things as non-static and remove unused code.
Also, build the URI instead of hardcoding things. Assume HTTPS over 443 unless specified
2022-12-13 09:16:32 -08:00
d478291c6b Update readme 2022-12-10 20:53:00 -08:00
f38afd75b8 Fix layout 2022-12-10 20:48:37 -08:00
daf04140ee Make the app more configurable by setting AS's accordingly 2022-12-10 20:47:52 -08:00
fe35067549 Clean up front end code 2022-12-10 20:34:39 -08:00
e7ee6ada7c Let the year dynamically update itself 2022-12-10 20:18:18 -08:00
6b51a91685 Implement tags since adding tags can crash the app on the netbox side 2022-12-10 20:08:00 -08:00
18 changed files with 361 additions and 3013 deletions

30
.dockerignore Normal file
View File

@@ -0,0 +1,30 @@
**/.classpath
**/.dockerignore
**/.env
**/.git
**/.gitignore
**/.project
**/.settings
**/.toolstarget
**/.vs
**/.vscode
**/*.*proj.user
**/*.dbmdl
**/*.jfm
**/azds.yaml
**/bin
**/charts
**/docker-compose*
**/Dockerfile*
**/node_modules
**/npm-debug.log
**/obj
**/secrets.dev.yaml
**/values.dev.yaml
LICENSE
README.md
!**/.gitignore
!.git/HEAD
!.git/config
!.git/packed-refs
!.git/refs/heads/**

View File

@@ -1,14 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk.Web"> <Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net6.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="13.0.2" /> <PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.19.5" />
<PackageReference Include="System.Text.Json" Version="6.0.7" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@@ -1,51 +1,40 @@
using AS1024.CommunityDocumentationPage.Models; using AS1024.CommunityDocumentationPage.Models;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using System.Diagnostics; using System.Diagnostics;
using NetBox; using AS1024.CommunityDocumentationPage.Interfaces;
using System.Net.Http;
using System.Net.Http.Headers;
using Newtonsoft.Json;
namespace AS1024.CommunityDocumentationPage.Controllers namespace AS1024.CommunityDocumentationPage.Controllers
{ {
public class HomeController : Controller public class HomeController : Controller
{ {
private readonly ILogger<HomeController> _logger; private readonly ILogger<HomeController> _logger;
private readonly IBgpCommunity _bgpCommunity;
private IConfiguration Configuration { get; } private readonly IConfiguration _configuration;
public HomeController(ILogger<HomeController> logger, public HomeController(ILogger<HomeController> logger,
IConfiguration configuration) IConfiguration configuration,
IBgpCommunity bgpCommunity)
{ {
_logger = logger; _logger = logger;
Configuration = configuration; _configuration = configuration;
_bgpCommunity = bgpCommunity;
} }
public async Task<IActionResult> IndexAsync() [ResponseCache(Duration = 3600)]
{ public async Task<IActionResult> Index()
var results = await ReadAPI(Configuration["APIKey"]);
var filtered = results.Results.Where(b => b.Name.StartsWith(Configuration["ASN"]))
.ToList();
return View(filtered);
}
private static async Task<RouteTargets> ReadAPI(string token)
{ {
try try
{ {
HttpClient client = new(); var result =
client.DefaultRequestHeaders.Clear(); await _bgpCommunity.GetCommunities();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Token", token); return View(result);
var result = await client.GetAsync("https://netbox.as1024.net/api/ipam/route-targets/"); } catch (Exception ex)
var stringResult = await result.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject<RouteTargets>(stringResult);
} catch
{ {
throw new Exception("Something went wrong?"); _logger.LogError($"Failed to obtain data\n{ex}");
} }
return NotFound();
} }
public IActionResult Privacy() public IActionResult Privacy()

View File

@@ -0,0 +1,59 @@
using AS1024.CommunityDocumentationPage.Interfaces;
using AS1024.CommunityDocumentationPage.Models;
using System.Text.Json;
using System.Net.Http.Headers;
namespace AS1024.CommunityDocumentationPage.DIScopes
{
public class NetBoxBgpCommunities : IBgpCommunity
{
protected readonly IConfiguration _configuration;
public NetBoxBgpCommunities(IConfiguration configuration)
{
_configuration = configuration;
}
string IBgpCommunity.DcimName => "netbox";
public async Task<ICollection<CommunityTag>> GetCommunities()
{
var Tags = new List<CommunityTag>();
using HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Token", _configuration["APIKey"]);
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage result = await client.GetAsync(BuildNetBoxURI());
string stringResult = await result.Content.ReadAsStringAsync();
var temp =
JsonSerializer.Deserialize<RouteTargets>(stringResult, new JsonSerializerOptions{
PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower
});
foreach (var route in temp.Results)
{
var community = new CommunityTag
{
ASN = int.Parse(route.Name.Split(':')[0]),
CommunityValue = int.Parse(route.Name.Split(':')[1]),
Description = route.Description,
Tag = route.Tags
};
Tags.Add(community);
}
return Tags.OrderBy(b => b.ASN)
.ThenBy(b => b.CommunityValue)
.ToList();
}
protected Uri BuildNetBoxURI()
{
UriBuilder endUrl = new UriBuilder
{
Path = "/api/ipam/route-targets/",
Host = _configuration["NetBoxHost"],
Scheme = "https"
};
return endUrl.Uri;
}
}
}

View File

@@ -0,0 +1,43 @@
using AS1024.CommunityDocumentationPage.Interfaces;
using AS1024.CommunityDocumentationPage.Models;
using System.Net.Http.Headers;
using System.Text.Json;
namespace AS1024.CommunityDocumentationPage.DIScopes
{
public class NetboxBgpCommunityDocumentation : IBgpCommunityDocumentation
{
private readonly IConfiguration configuration;
public string DcimName => "netbox";
public NetboxBgpCommunityDocumentation(IConfiguration configuration)
{
this.configuration = configuration;
}
public async Task<RouteTargets> GetBgpCommunities()
{
using HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Token", configuration["APIKey"]);
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage result = await client.GetAsync(BuildNetBoxURI());
string stringResult = await result.Content.ReadAsStringAsync();
#pragma warning disable CS8603 // Possible null reference return.
return JsonSerializer.Deserialize<RouteTargets>(stringResult,
new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower });
#pragma warning restore CS8603 // Possible null reference return.
}
protected Uri BuildNetBoxURI()
{
UriBuilder endUrl = new UriBuilder
{
Path = "/api/ipam/route-targets/",
Host = configuration["NetBoxHost"],
Scheme = "https"
};
return endUrl.Uri;
}
}
}

View File

@@ -0,0 +1,26 @@
namespace AS1024.CommunityDocumentationPage.DIScopes
{
public static class ValidateBgpCommunity
{
/// <summary>
/// validates if this is a valid standard BGP Community
/// </summary>
/// <param name="Community">Community string represented as NNN:XXX</param>
/// <returns>true if it's a valid bgp community, false if it isn't</returns>
public static bool IsValidBgpCommunity(this string Community)
{
string[] splitStrings =
Community.Split(":", StringSplitOptions.RemoveEmptyEntries);
for (int i = 0; i < 1; i++)
{
if (!int.TryParse(splitStrings[i], out int communityParsed)
&& communityParsed > 65536)
{
return false;
}
}
return true;
}
}
}

View File

@@ -0,0 +1,26 @@
#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/aspnet:8.0 AS base
USER app
WORKDIR /app
EXPOSE 8080
FROM --platform=$BUILDPLATFORM mcr.microsoft.com/dotnet/sdk:8.0 AS build
ARG BUILD_CONFIGURATION=Release
ARG TARGETARCH
WORKDIR /src
COPY ["AS1024.CommunityDocumentationPage/AS1024.CommunityDocumentationPage.csproj", "AS1024.CommunityDocumentationPage/"]
RUN dotnet restore "./AS1024.CommunityDocumentationPage/./AS1024.CommunityDocumentationPage.csproj" -a $TARGETARCH
COPY . .
WORKDIR "/src/AS1024.CommunityDocumentationPage"
RUN dotnet build "./AS1024.CommunityDocumentationPage.csproj" -c $BUILD_CONFIGURATION -o /app/build -a $TARGETARCH
FROM --platform=$BUILDPLATFORM build AS publish
ARG BUILD_CONFIGURATION=Release
ARG TARGETARCH
RUN dotnet publish "./AS1024.CommunityDocumentationPage.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false -a $TARGETARCH
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "AS1024.CommunityDocumentationPage.dll"]

View File

@@ -0,0 +1,35 @@
using AS1024.CommunityDocumentationPage.Models;
namespace AS1024.CommunityDocumentationPage.Interfaces
{
/// <summary>
/// Abstraction layer on obtaining BGP communities regardless of DCIM system
/// </summary>
public interface IBgpCommunityDocumentation
{
/// <summary>
/// Read Only field on what the constructor grabs it's data from
/// </summary>
string DcimName { get; }
/// <summary>
/// Gets a list of BGP Communities
/// </summary>
/// <returns></returns>
Task<RouteTargets> GetBgpCommunities();
}
/// <summary>
///
/// </summary>
public interface IBgpCommunity
{
/// <summary>
///
/// </summary>
string DcimName { get; }
/// <summary>
///
/// </summary>
/// <returns></returns>
Task<ICollection<CommunityTag>> GetCommunities();
}
}

View File

@@ -0,0 +1,37 @@
namespace AS1024.CommunityDocumentationPage.Models
{
/// <summary>
///
/// </summary>
public class BgpCommunity
{
/// <summary>
/// Community Tag
/// </summary>
public string CommunityTag { get; set; }
/// <summary>
/// Type of BGP Community
/// </summary>
public CommunityType BgpCommunityType { get; set; }
/// <summary>
/// What the community does
/// </summary>
public string CommunityDescription { get; set; }
}
public enum CommunityType
{
/// <summary>
/// 32 bit community
/// </summary>
Community,
/// <summary>
/// Extended community with RT
/// </summary>
ExtendedCommunity,
/// <summary>
/// Large BGP Community
/// </summary>
LargeCommunity
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -12,7 +12,7 @@
public string Name { get; set; } public string Name { get; set; }
public string Tenant { get; set; } public string Tenant { get; set; }
public string Description { get; set; } public string Description { get; set; }
public IList<string> Tags { get; set; } public IList<Tag> Tags { get; set; }
public CustomFields CustomFields { get; set; } public CustomFields CustomFields { get; set; }
public DateTime Created { get; set; } public DateTime Created { get; set; }
public DateTime LastUpdated { get; set; } public DateTime LastUpdated { get; set; }
@@ -25,4 +25,23 @@
public object Previous { get; set; } public object Previous { get; set; }
public IList<Result> Results { get; set; } public IList<Result> Results { get; set; }
} }
public class Tag
{
public int id { get; set; }
public string url { get; set; }
public string display { get; set; }
public string name { get; set; }
public string slug { get; set; }
public string color { get; set; }
}
public class CommunityTag
{
public int ASN { get; set; }
public int CommunityValue { get; set; }
public string FormattedVaule => $"{this.ASN}:{this.CommunityValue}";
public string? Description { get; set; }
public IList<Tag>? Tag { get; set; }
}
} }

View File

@@ -1,8 +1,14 @@
using AS1024.CommunityDocumentationPage.DIScopes;
using AS1024.CommunityDocumentationPage.Interfaces;
var builder = WebApplication.CreateBuilder(args); var builder = WebApplication.CreateBuilder(args);
// Add services to the container. // Add services to the container.
builder.Services.AddControllersWithViews(); builder.Services.AddControllersWithViews();
builder.Services.AddTransient<IBgpCommunityDocumentation, NetboxBgpCommunityDocumentation>();
builder.Services.AddTransient<IBgpCommunity, NetBoxBgpCommunities>();
var app = builder.Build(); var app = builder.Build();
// Configure the HTTP request pipeline. // Configure the HTTP request pipeline.

View File

@@ -1,21 +1,12 @@
{ {
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:49374",
"sslPort": 0
}
},
"profiles": { "profiles": {
"AS1024.CommunityDocumentationPage": { "AS1024.CommunityDocumentationPage": {
"commandName": "Project", "commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true, "launchBrowser": true,
"applicationUrl": "http://localhost:5224",
"environmentVariables": { "environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development" "ASPNETCORE_ENVIRONMENT": "Development"
} },
"applicationUrl": "http://localhost:5224"
}, },
"IIS Express": { "IIS Express": {
"commandName": "IISExpress", "commandName": "IISExpress",
@@ -23,6 +14,23 @@
"environmentVariables": { "environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development" "ASPNETCORE_ENVIRONMENT": "Development"
} }
},
"Docker": {
"commandName": "Docker",
"launchBrowser": true,
"launchUrl": "{Scheme}://{ServiceHost}:{ServicePort}",
"environmentVariables": {
"ASPNETCORE_HTTP_PORTS": "8080"
},
"publishAllPorts": true
}
},
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:49374",
"sslPort": 0
} }
} }
} }

View File

@@ -1,24 +1,33 @@
@model List<AS1024.CommunityDocumentationPage.Models.Result> @using Microsoft.Extensions.DependencyInjection
@inject IConfiguration Configuration
@model List<AS1024.CommunityDocumentationPage.Models.CommunityTag>
@{ @{
ViewData["Title"] = "BGP Communities"; ViewData["Title"] = "BGP Communities";
} }
<p>This site contains BGP communities for AS1024. Please note that these communities are subject to change at a moment's notice. We do not strip communities on received routes or on routes sent to peers and upstreams, but we cannot guarantee that the communities will be preserved by the upstream or peers. If you have any questions or need support, please reach out to noc@12393239.xyz.</p> <p>This site contains BGP communities for @("AS" + Configuration["ASN"]). Please note that these communities are subject to change at a moment's notice. We do not strip communities on received routes or on routes sent to peers and upstreams, but we cannot guarantee that the communities will be preserved by the upstream or peers. If you have any questions or need support, please reach out to <a href="mailto:@Configuration["NOCEmail"]">@Configuration["NOCEmail"].</a></p>
<p>The communities are as follows:</p> <p>The communities are as follows:</p>
<div class="table-responsive">
<table class="table"> <table class="table table-hover">
<thead> <thead>
<tr> <tr>
<th>Community Tag</th> <th scope="col">Community Tag</th>
<th>Description</th> <th scope="col">Description</th>
<th scope="col">Community Type</th>
</tr> </tr>
</thead> </thead>
@foreach (var item in Model) { @foreach (var item in Model) {
<tr> <tr>
<td>@item.Name</td> <td scope="row">@item.FormattedVaule</td>
<td>@item.Description</td> <td scope="row">@item.Description</td>
<td scope="row">
@foreach (var tags in item.Tag) {
<div class="d-inline-flex p-2 text-white" style="background-color:#@tags.color">@tags.display</div>
}
</td>
</tr> </tr>
} }
</table> </table>
</div>

View File

@@ -1,6 +0,0 @@
@{
ViewData["Title"] = "Privacy Policy";
}
<h1>@ViewData["Title"]</h1>
<p>Use this page to detail your site's privacy policy.</p>

View File

@@ -1,9 +1,11 @@
<!DOCTYPE html> @using Microsoft.Extensions.Hosting
@inject IConfiguration Configuration
<!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@ViewData["Title"] - AS1024 NetOps</title> <title>@ViewData["Title"] - @("AS" + Configuration["ASN"]) NetOps</title>
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" /> <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" />
<link rel="stylesheet" href="~/css/site.css" asp-append-version="true" /> <link rel="stylesheet" href="~/css/site.css" asp-append-version="true" />
<link rel="stylesheet" href="~/AS1024.CommunityDocumentationPage.styles.css" asp-append-version="true" /> <link rel="stylesheet" href="~/AS1024.CommunityDocumentationPage.styles.css" asp-append-version="true" />
@@ -12,7 +14,7 @@
<header> <header>
<nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3"> <nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
<div class="container-fluid"> <div class="container-fluid">
<a class="navbar-brand" asp-area="" asp-controller="Home" asp-action="Index">AS1024 Net Ops</a> <a class="navbar-brand" asp-area="" asp-controller="Home" asp-action="Index">@("AS" + Configuration["ASN"]) Net Ops</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target=".navbar-collapse" aria-controls="navbarSupportedContent" <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target=".navbar-collapse" aria-controls="navbarSupportedContent"
aria-expanded="false" aria-label="Toggle navigation"> aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span> <span class="navbar-toggler-icon"></span>
@@ -35,7 +37,7 @@
<footer class="border-top footer text-muted"> <footer class="border-top footer text-muted">
<div class="container"> <div class="container">
&copy; 2022 - AS1024.net &copy; @DateTime.Now.Year - @("AS" + Configuration["ASN"] + ".net")
</div> </div>
</footer> </footer>
<script src="~/lib/jquery/dist/jquery.min.js"></script> <script src="~/lib/jquery/dist/jquery.min.js"></script>

View File

@@ -6,6 +6,8 @@
} }
}, },
"APIKey": "", "APIKey": "",
"ASN": "1024", "ASN": "",
"AllowedHosts": "*" "NOCEmail": "",
"AllowedHosts": "*",
"NetBoxHost" : ""
} }

View File

@@ -26,3 +26,5 @@ This web app must be configured with asppsettings.json with the following values
- ``APIKey`` - This is a netbox API Key. We strongly recommend that you do this as a read only thing - ``APIKey`` - This is a netbox API Key. We strongly recommend that you do this as a read only thing
- ``ASN`` - This is required, without it, the AS's will not display properly - ``ASN`` - This is required, without it, the AS's will not display properly
- ``NOCEmail`` - This is to display for NOC E-Mail Inquries
- ``NetBoxHostname`` - The hostname to communicate to the netbox instance - This always assumes your netbox instance is secured by TLS running on port 443