-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
3678cf3
commit 531cbde
Showing
44 changed files
with
566 additions
and
28 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
name: .NET | ||
|
||
on: | ||
push: | ||
tags: | ||
- 'v*' | ||
|
||
jobs: | ||
build: | ||
|
||
runs-on: ubuntu-latest | ||
|
||
steps: | ||
- uses: actions/checkout@v3 | ||
- name: Setup .NET | ||
uses: actions/setup-dotnet@v2 | ||
with: | ||
dotnet-version: 6.0.104 | ||
- name: Restore dependencies | ||
run: dotnet restore | ||
- name: Build | ||
run: dotnet build --no-restore | ||
- name: Test | ||
run: dotnet test --no-build --verbosity normal | ||
- name: Pack NuGet | ||
run: dotnet pack -c Release --version-suffix preview.1.`date +%y%m%d%H%M` -o ./ | ||
- name: Push NuGet | ||
run: dotnet nuget push '*.nupkg' -s https://api.nuget.org/v3/index.json -k ${{ secrets.NUGET_API_KEY }} -n true --skip-duplicate | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
<Project> | ||
<PropertyGroup Condition="'$(TargetFramework)' == 'net6.0'"> | ||
<FrameworkVersion>6.0.0</FrameworkVersion> | ||
<ExtensionsVersion>6.0.0</ExtensionsVersion> | ||
</PropertyGroup> | ||
<PropertyGroup Condition="'$(TargetFramework)' == 'net7.0'"> | ||
<FrameworkVersion>7.0.0</FrameworkVersion> | ||
<ExtensionsVersion>7.0.0</ExtensionsVersion> | ||
</PropertyGroup> | ||
<PropertyGroup Condition="'$(TargetFramework)' == 'net8.0'"> | ||
<FrameworkVersion>8.0.0</FrameworkVersion> | ||
<ExtensionsVersion>8.0.0</ExtensionsVersion> | ||
</PropertyGroup> | ||
<ItemGroup> | ||
<!--microsoft extensions --> | ||
<PackageReference Update="Microsoft.Extensions.Configuration.Abstractions" Version="$(ExtensionsVersion)"/> | ||
<PackageReference Update="Microsoft.Extensions.Configuration" Version="$(ExtensionsVersion)"/> | ||
<PackageReference Update="Microsoft.Extensions.DependencyInjection.Abstractions" Version="$(ExtensionsVersion)"/> | ||
<PackageReference Update="Microsoft.Extensions.DependencyInjection" Version="$(ExtensionsVersion)"/> | ||
<PackageReference Update="Microsoft.Extensions.Logging.Abstractions" Version="$(ExtensionsVersion)"/> | ||
<PackageReference Update="Microsoft.Extensions.Options" Version="$(ExtensionsVersion)"/> | ||
<PackageReference Update="Microsoft.Extensions.Logging" Version="$(ExtensionsVersion)"/> | ||
<PackageReference Update="Microsoft.Extensions.Logging.Console" Version="$(ExtensionsVersion)"/> | ||
<PackageReference Update="Microsoft.Extensions.FileProviders.Embedded" Version="$(ExtensionsVersion)"/> | ||
|
||
<PackageReference Update="Microsoft.AspNetCore.Mvc.Testing" Version="$(FrameworkVersion)" /> | ||
<PackageReference Update="Microsoft.NET.Test.Sdk" Version="17.6.2" /> | ||
<PackageReference Update="Moq" Version="4.18.4" /> | ||
<PackageReference Update="xunit" Version="2.4.2" /> | ||
<PackageReference Update="xunit.runner.visualstudio" Version="2.4.5"> | ||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> | ||
<PrivateAssets>all</PrivateAssets> | ||
</PackageReference> | ||
<PackageReference Update="coverlet.collector" Version="6.0.0"> | ||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> | ||
<PrivateAssets>all</PrivateAssets> | ||
</PackageReference> | ||
</ItemGroup> | ||
</Project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,35 @@ | ||
# netcorepal-extensions-yarp | ||
|
||
NetCorePal Extensions for YAEP | ||
[![Release Build](https://img.shields.io/github/actions/workflow/status/netcorepal/netcorepal-extensions-yarp/release.yml?label=release%20build)](https://github.com/netcorepal/netcorepal-extensions-yarp/actions/workflows/release.yml) | ||
[![Preview Build](https://img.shields.io/github/actions/workflow/status/netcorepal/netcorepal-extensions-yarp/dotnet.yml?label=preview%20build)](https://github.com/netcorepal/netcorepal-extensions-yarp/actions/workflows/dotnet.yml) | ||
[![NuGet](https://img.shields.io/nuget/v/NetCorePal.Yarp.ReverseProxy.Dashboard.svg)](https://www.nuget.org/packages/NetCorePal.Yarp.ReverseProxy.Dashboard) | ||
[![MyGet Preview](https://img.shields.io/myget/netcorepal/vpre/NetCorePal.Yarp.ReverseProxy.Dashboard?label=preview)](https://www.myget.org/feed/netcorepal/package/nuget/NetCorePal.Yarp.ReverseProxy.Dashboard) | ||
[![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/netcorepal/netcorepal-extensions-yarp/blob/main/LICENSE) | ||
|
||
The Extensions for [YAEP](https://github.com/microsoft/reverse-proxy) | ||
|
||
## Package List | ||
|
||
|Package|Release|Preview| | ||
|---|---|---| | ||
|NetCorePal.Yarp.ReverseProxy.Dashboard|[![NuGet](https://img.shields.io/nuget/v/NetCorePal.Yarp.ReverseProxy.Dashboard.svg)](https://www.nuget.org/packages/NetCorePal.Yarp.ReverseProxy.Dashboard)|[![MyGet Preview](https://img.shields.io/myget/netcorepal/vpre/NetCorePal.Yarp.ReverseProxy.Dashboard?label=preview)](https://www.myget.org/feed/netcorepal/package/nuget/NetCorePal.Yarp.ReverseProxy.Dashboard)| | ||
|NetCorePal.Yarp.Kubernetes.Controller.IngressCertificates|[![NuGet](https://img.shields.io/nuget/v/NetCorePal.Yarp.Kubernetes.Controller.IngressCertificates.svg)](https://www.nuget.org/packages/NetCorePal.Yarp.Kubernetes.Controller.IngressCertificates)|[![MyGet Preview](https://img.shields.io/myget/netcorepal/vpre/NetCorePal.Yarp.Kubernetes.Controller.IngressCertificates?label=preview)](https://www.myget.org/feed/netcorepal/package/nuget/NetCorePal.Yarp.Kubernetes.Controller.IngressCertificates)| | ||
|
||
## Preview Build | ||
|
||
Preview NuGet Feed: | ||
|
||
```text | ||
https://www.myget.org/F/netcorepal/api/v3/index.json | ||
``` | ||
|
||
NuGet.config: | ||
|
||
```xml | ||
<?xml version="1.0" encoding="utf-8"?> | ||
<configuration> | ||
<packageSources> | ||
<add key="netcorepal" value="https://www.myget.org/F/netcorepal/api/v3/index.json" /> | ||
</packageSources> | ||
</configuration> | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,6 @@ | ||
<Project> | ||
<PropertyGroup> | ||
<VersionPrefix>0.1.0</VersionPrefix> | ||
<VersionPrefix>0.2.0</VersionPrefix> | ||
<VersionSuffix></VersionSuffix> | ||
</PropertyGroup> | ||
</Project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
148 changes: 148 additions & 0 deletions
148
...CorePal.Yarp.Kubernetes.Controller.IngressCertificates/IngressServerCertificateManager.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,148 @@ | ||
using System.Collections.Concurrent; | ||
using System.Security.Cryptography.X509Certificates; | ||
using k8s; | ||
using k8s.Models; | ||
using Microsoft.AspNetCore.Connections; | ||
using Microsoft.Extensions.Hosting; | ||
using Microsoft.Extensions.Logging; | ||
using Yarp.Kubernetes.Controller; | ||
using Yarp.Kubernetes.Controller.Caching; | ||
using Yarp.Kubernetes.Controller.Certificates; | ||
using Yarp.Kubernetes.Controller.Client; | ||
|
||
namespace NetCorePal.Yarp.Kubernetes.Controller.IngressCertificates; | ||
|
||
public class IngressServerCertificateManager : IHostedService | ||
{ | ||
private readonly IngressServerCertificateSelector _certificateSelector; | ||
|
||
private readonly object _lock = new object(); | ||
|
||
private readonly ICache _cache; | ||
|
||
private readonly ILogger _logger; | ||
|
||
private readonly ConcurrentDictionary<NamespacedName, X509Certificate2> _secrets = new(); | ||
|
||
private readonly ICertificateHelper _certificateHelper; | ||
|
||
public IngressServerCertificateManager( | ||
IngressServerCertificateSelector certificateSelector, | ||
ICache cache, | ||
ICertificateHelper certificateHelper, | ||
IResourceInformer<V1Secret> secretInformer, | ||
IResourceInformer<V1Ingress> ingressInformer, | ||
ILogger<IngressServerCertificateManager> logger) | ||
{ | ||
_certificateSelector = certificateSelector; | ||
_cache = cache; | ||
_certificateHelper = certificateHelper; | ||
secretInformer.Register(Update); | ||
ingressInformer.Register(Update); | ||
_logger = logger; | ||
} | ||
|
||
private void Update(WatchEventType eventType, V1Ingress ingress) | ||
{ | ||
try | ||
{ | ||
ResetCertificates(); | ||
} | ||
catch (Exception e) | ||
{ | ||
_logger.LogError(e, "Update ingress certificate error when update ingress"); | ||
} | ||
} | ||
|
||
private void Update(WatchEventType eventType, V1Secret resource) | ||
{ | ||
try | ||
{ | ||
NamespacedName n = new NamespacedName(resource.Namespace(), resource.Name()); | ||
switch (eventType) | ||
{ | ||
case WatchEventType.Added: | ||
case WatchEventType.Modified: | ||
_secrets.TryAdd(n, _certificateHelper.ConvertCertificate(n, resource)); | ||
break; | ||
case WatchEventType.Deleted: | ||
_secrets.TryRemove(n, out _); | ||
break; | ||
} | ||
|
||
ResetCertificates(); | ||
} | ||
catch (Exception e) | ||
{ | ||
_logger.LogError(e, "Update ingress certificate error when update secret"); | ||
} | ||
} | ||
|
||
|
||
private void ResetCertificates() | ||
{ | ||
lock (_lock) | ||
{ | ||
var certs = new Dictionary<string, X509Certificate2>(); | ||
var wildcardCerts = new Dictionary<string, X509Certificate2>(); | ||
foreach (var ingress in _cache.GetIngresses()) | ||
{ | ||
if (ingress.Spec?.Tls == null) continue; | ||
|
||
foreach (var tls in ingress.Spec.Tls) | ||
{ | ||
if (!string.IsNullOrEmpty(tls.SecretName)) | ||
{ | ||
var secretName = new NamespacedName(ingress.Metadata.Namespace(), tls.SecretName); | ||
if (_secrets.TryGetValue(secretName, out var certificate)) | ||
{ | ||
foreach (var host in tls.Hosts) | ||
{ | ||
if (IsWildcardDomain(host)) | ||
{ | ||
wildcardCerts[host] = certificate; | ||
} | ||
else | ||
{ | ||
certs[host] = certificate; | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} | ||
|
||
Interlocked.Exchange(ref _certificateSelector._domainCertificates, certs); | ||
Interlocked.Exchange(ref _certificateSelector._wildcardDomainCertificates, wildcardCerts); | ||
} | ||
} | ||
|
||
|
||
bool IsWildcardDomain(string domainName) | ||
{ | ||
return domainName.StartsWith("*", StringComparison.Ordinal); | ||
} | ||
|
||
bool TryToWildcardDomain(string domainName, out string wildcardDomainName) | ||
{ | ||
wildcardDomainName = string.Empty; | ||
var index = domainName.IndexOf(".", StringComparison.Ordinal); | ||
if (index == -1) | ||
{ | ||
return false; | ||
} | ||
|
||
wildcardDomainName = string.Concat("*", domainName.AsSpan(index)); | ||
return true; | ||
} | ||
|
||
public Task StartAsync(CancellationToken cancellationToken) | ||
{ | ||
return Task.CompletedTask; | ||
} | ||
|
||
public Task StopAsync(CancellationToken cancellationToken) | ||
{ | ||
return Task.CompletedTask; | ||
} | ||
} |
55 changes: 55 additions & 0 deletions
55
...orePal.Yarp.Kubernetes.Controller.IngressCertificates/IngressServerCertificateSelector.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
using System.Security.Cryptography.X509Certificates; | ||
using Microsoft.AspNetCore.Connections; | ||
using Yarp.Kubernetes.Controller; | ||
using Yarp.Kubernetes.Controller.Certificates; | ||
|
||
namespace NetCorePal.Yarp.Kubernetes.Controller.IngressCertificates; | ||
|
||
public class IngressServerCertificateSelector : IServerCertificateSelector | ||
{ | ||
private X509Certificate2? _defaultCertificate = null; | ||
|
||
internal volatile Dictionary<string, X509Certificate2> _domainCertificates = new(); | ||
|
||
internal volatile Dictionary<string, X509Certificate2> _wildcardDomainCertificates = new(); | ||
|
||
|
||
public X509Certificate2? GetCertificate(ConnectionContext connectionContext, string domainName) | ||
{ | ||
if (_domainCertificates.TryGetValue(domainName, out var certificate)) | ||
{ | ||
return certificate; | ||
} | ||
|
||
if (TryToWildcardDomain(domainName, out var wildcardDomainName) | ||
&& _wildcardDomainCertificates.TryGetValue(wildcardDomainName, out var certificate1)) | ||
{ | ||
return certificate1; | ||
} | ||
|
||
return _defaultCertificate; | ||
} | ||
|
||
public void AddCertificate(NamespacedName certificateName, X509Certificate2 certificate) | ||
{ | ||
_defaultCertificate = certificate; | ||
} | ||
|
||
public void RemoveCertificate(NamespacedName certificateName) | ||
{ | ||
_defaultCertificate = null; | ||
} | ||
|
||
bool TryToWildcardDomain(string domainName, out string wildcardDomainName) | ||
{ | ||
wildcardDomainName = string.Empty; | ||
var index = domainName.IndexOf(".", StringComparison.Ordinal); | ||
if (index == -1) | ||
{ | ||
return false; | ||
} | ||
|
||
wildcardDomainName = string.Concat("*", domainName.AsSpan(index)); | ||
return true; | ||
} | ||
} |
Oops, something went wrong.