+semver: upgrade to net5.0 (#1390)

* breaking upgrade base build image to net5.0

* add make and build tools to image

* fix code broken after net5.0 upgrade

* fix warnings

* fix tests and line endings

* upgrade dotnet test and coverages packages

* update circle build image

* removed rafty and updated more packages

* bring back develop

* rename authorisation to authorization
This commit is contained in:
Tom Pallister
2020-12-11 09:54:08 +00:00
committed by GitHub
parent c3a0cf1160
commit b74a1197a2
130 changed files with 4766 additions and 6210 deletions

View File

@@ -1,39 +1,39 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<NoPackageAnalysis>true</NoPackageAnalysis>
<Description>Provides Ocelot extensions to use the administration API and IdentityService dependencies that come with it</Description>
<AssemblyTitle>Ocelot.Administration</AssemblyTitle>
<VersionPrefix>0.0.0-dev</VersionPrefix>
<AssemblyName>Ocelot.Administration</AssemblyName>
<PackageId>Ocelot.Administration</PackageId>
<PackageTags>API Gateway;.NET core</PackageTags>
<PackageProjectUrl>https://github.com/ThreeMammals/Ocelot.Administration</PackageProjectUrl>
<PackageProjectUrl>https://github.com/ThreeMammals/Ocelot.Administration</PackageProjectUrl>
<PackageIconUrl>http://threemammals.com/images/ocelot_logo.png</PackageIconUrl>
<RuntimeIdentifiers>win10-x64;osx.10.11-x64;osx.10.12-x64;win7-x64</RuntimeIdentifiers>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<Authors>Tom Pallister</Authors>
<CodeAnalysisRuleSet>..\..\codeanalysis.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<DebugType>full</DebugType>
<DebugSymbols>True</DebugSymbols>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Ocelot\Ocelot.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.164">
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="IdentityServer4.AccessTokenValidation" Version="3.0.1" />
<PackageReference Include="IdentityServer4" Version="3.1.1" />
</ItemGroup>
<ItemGroup>
<PackageReference Update="Microsoft.SourceLink.GitHub" Version="1.0.0" />
</ItemGroup>
</Project>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
<NoPackageAnalysis>true</NoPackageAnalysis>
<Description>Provides Ocelot extensions to use the administration API and IdentityService dependencies that come with it</Description>
<AssemblyTitle>Ocelot.Administration</AssemblyTitle>
<VersionPrefix>0.0.0-dev</VersionPrefix>
<AssemblyName>Ocelot.Administration</AssemblyName>
<PackageId>Ocelot.Administration</PackageId>
<PackageTags>API Gateway;.NET core</PackageTags>
<PackageProjectUrl>https://github.com/ThreeMammals/Ocelot.Administration</PackageProjectUrl>
<PackageProjectUrl>https://github.com/ThreeMammals/Ocelot.Administration</PackageProjectUrl>
<PackageIconUrl>http://threemammals.com/images/ocelot_logo.png</PackageIconUrl>
<RuntimeIdentifiers>win10-x64;osx.10.11-x64;osx.10.12-x64;win7-x64</RuntimeIdentifiers>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<Authors>Tom Pallister</Authors>
<CodeAnalysisRuleSet>..\..\codeanalysis.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<DebugType>full</DebugType>
<DebugSymbols>True</DebugSymbols>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Ocelot\Ocelot.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.164">
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="IdentityServer4.AccessTokenValidation" Version="3.0.1" />
<PackageReference Include="IdentityServer4" Version="4.1.1" />
</ItemGroup>
<ItemGroup>
<PackageReference Update="Microsoft.SourceLink.GitHub" Version="1.0.0" />
</ItemGroup>
</Project>

View File

@@ -1,7 +1,6 @@
using Ocelot.DependencyInjection;
using IdentityServer4.AccessTokenValidation;
using IdentityServer4.Models;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
@@ -10,6 +9,9 @@ using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Cryptography.X509Certificates;
using System.Linq;
using Microsoft.IdentityModel.Tokens;
using Microsoft.AspNetCore.Authentication.JwtBearer;
namespace Ocelot.Administration
{
@@ -18,6 +20,7 @@ namespace Ocelot.Administration
public static IOcelotAdministrationBuilder AddAdministration(this IOcelotBuilder builder, string path, string secret)
{
var administrationPath = new AdministrationPath(path);
builder.Services.AddSingleton<OcelotMiddlewareConfigurationDelegate>(IdentityServerMiddlewareConfigurationProvider.Get);
//add identity server for admin area
@@ -32,7 +35,7 @@ namespace Ocelot.Administration
return new OcelotAdministrationBuilder(builder.Services, builder.Configuration);
}
public static IOcelotAdministrationBuilder AddAdministration(this IOcelotBuilder builder, string path, Action<IdentityServerAuthenticationOptions> configureOptions)
public static IOcelotAdministrationBuilder AddAdministration(this IOcelotBuilder builder, string path, Action<JwtBearerOptions> configureOptions)
{
var administrationPath = new AdministrationPath(path);
builder.Services.AddSingleton<OcelotMiddlewareConfigurationDelegate>(IdentityServerMiddlewareConfigurationProvider.Get);
@@ -46,11 +49,11 @@ namespace Ocelot.Administration
return new OcelotAdministrationBuilder(builder.Services, builder.Configuration);
}
private static void AddIdentityServer(Action<IdentityServerAuthenticationOptions> configOptions, IOcelotBuilder builder)
private static void AddIdentityServer(Action<JwtBearerOptions> configOptions, IOcelotBuilder builder)
{
builder.Services
.AddAuthentication(IdentityServerAuthenticationDefaults.AuthenticationScheme)
.AddIdentityServerAuthentication(configOptions);
.AddJwtBearer("Bearer", configOptions);
}
private static void AddIdentityServer(IIdentityServerConfiguration identityServerConfiguration, IAdministrationPath adminPath, IOcelotBuilder builder, IConfiguration configuration)
@@ -60,7 +63,9 @@ namespace Ocelot.Administration
.AddIdentityServer(o =>
{
o.IssuerUri = "Ocelot";
o.EmitStaticAudienceClaim = true;
})
.AddInMemoryApiScopes(ApiScopes(identityServerConfiguration))
.AddInMemoryApiResources(Resources(identityServerConfiguration))
.AddInMemoryClients(Client(identityServerConfiguration));
@@ -68,14 +73,17 @@ namespace Ocelot.Administration
var baseSchemeUrlAndPort = urlFinder.Find();
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
builder.Services.AddAuthentication(IdentityServerAuthenticationDefaults.AuthenticationScheme)
.AddIdentityServerAuthentication(o =>
builder.Services
.AddAuthentication(IdentityServerAuthenticationDefaults.AuthenticationScheme)
.AddJwtBearer("Bearer", options =>
{
o.Authority = baseSchemeUrlAndPort + adminPath.Path;
o.ApiName = identityServerConfiguration.ApiName;
o.RequireHttpsMetadata = identityServerConfiguration.RequireHttps;
o.SupportedTokens = SupportedTokens.Both;
o.ApiSecret = identityServerConfiguration.ApiSecret;
options.Authority = baseSchemeUrlAndPort + adminPath.Path;
options.RequireHttpsMetadata = identityServerConfiguration.RequireHttps;
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateAudience = false,
};
});
//todo - refactor naming..
@@ -91,6 +99,11 @@ namespace Ocelot.Administration
}
}
private static IEnumerable<ApiScope> ApiScopes(IIdentityServerConfiguration identityServerConfiguration)
{
return identityServerConfiguration.AllowedScopes.Select(s => new ApiScope(s));
}
private static List<ApiResource> Resources(IIdentityServerConfiguration identityServerConfiguration)
{
return new List<ApiResource>
@@ -101,9 +114,9 @@ namespace Ocelot.Administration
{
new Secret
{
Value = identityServerConfiguration.ApiSecret.Sha256()
}
}
Value = identityServerConfiguration.ApiSecret.Sha256(),
},
},
},
};
}
@@ -117,8 +130,8 @@ namespace Ocelot.Administration
ClientId = identityServerConfiguration.ApiName,
AllowedGrantTypes = GrantTypes.ClientCredentials,
ClientSecrets = new List<Secret> {new Secret(identityServerConfiguration.ApiSecret.Sha256())},
AllowedScopes = { identityServerConfiguration.ApiName }
}
AllowedScopes = identityServerConfiguration.AllowedScopes,
},
};
}
}

View File

@@ -1,39 +1,39 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<NoPackageAnalysis>true</NoPackageAnalysis>
<Description>Provides Ocelot extensions to use CacheManager.Net</Description>
<AssemblyTitle>Ocelot.Cache.CacheManager</AssemblyTitle>
<VersionPrefix>0.0.0-dev</VersionPrefix>
<AssemblyName>Ocelot.Cache.CacheManager</AssemblyName>
<PackageId>Ocelot.Cache.CacheManager</PackageId>
<PackageTags>API Gateway;.NET core</PackageTags>
<PackageProjectUrl>https://github.com/ThreeMammals/Ocelot.Cache.CacheManager</PackageProjectUrl>
<PackageProjectUrl>https://github.com/ThreeMammals/Ocelot.Cache.CacheManager</PackageProjectUrl>
<RuntimeIdentifiers>win10-x64;osx.10.11-x64;osx.10.12-x64;win7-x64</RuntimeIdentifiers>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<Authors>Tom Pallister</Authors>
<CodeAnalysisRuleSet>..\..\codeanalysis.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<DebugType>full</DebugType>
<DebugSymbols>True</DebugSymbols>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Ocelot\Ocelot.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.164">
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="CacheManager.Core" Version="2.0.0-beta-1629" />
<PackageReference Include="CacheManager.Microsoft.Extensions.Configuration" Version="2.0.0-beta-1629" />
<PackageReference Include="CacheManager.Microsoft.Extensions.Logging" Version="2.0.0-beta-1629" />
</ItemGroup>
<ItemGroup>
<PackageReference Update="Microsoft.SourceLink.GitHub" Version="1.0.0" />
</ItemGroup>
</Project>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
<NoPackageAnalysis>true</NoPackageAnalysis>
<Description>Provides Ocelot extensions to use CacheManager.Net</Description>
<AssemblyTitle>Ocelot.Cache.CacheManager</AssemblyTitle>
<VersionPrefix>0.0.0-dev</VersionPrefix>
<AssemblyName>Ocelot.Cache.CacheManager</AssemblyName>
<PackageId>Ocelot.Cache.CacheManager</PackageId>
<PackageTags>API Gateway;.NET core</PackageTags>
<PackageProjectUrl>https://github.com/ThreeMammals/Ocelot.Cache.CacheManager</PackageProjectUrl>
<PackageProjectUrl>https://github.com/ThreeMammals/Ocelot.Cache.CacheManager</PackageProjectUrl>
<RuntimeIdentifiers>win10-x64;osx.10.11-x64;osx.10.12-x64;win7-x64</RuntimeIdentifiers>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<Authors>Tom Pallister</Authors>
<CodeAnalysisRuleSet>..\..\codeanalysis.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<DebugType>full</DebugType>
<DebugSymbols>True</DebugSymbols>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Ocelot\Ocelot.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.164">
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="CacheManager.Core" Version="2.0.0-beta-1629" />
<PackageReference Include="CacheManager.Microsoft.Extensions.Configuration" Version="2.0.0-beta-1629" />
<PackageReference Include="CacheManager.Microsoft.Extensions.Logging" Version="2.0.0-beta-1629" />
</ItemGroup>
<ItemGroup>
<PackageReference Update="Microsoft.SourceLink.GitHub" Version="1.0.0" />
</ItemGroup>
</Project>

View File

@@ -1,38 +1,38 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<NoPackageAnalysis>true</NoPackageAnalysis>
<Description>Provides Ocelot extensions to use Consul</Description>
<AssemblyTitle>Ocelot.Provider.Consul</AssemblyTitle>
<VersionPrefix>0.0.0-dev</VersionPrefix>
<AssemblyName>Ocelot.Provider.Consul</AssemblyName>
<PackageId>Ocelot.Provider.Consul</PackageId>
<PackageTags>API Gateway;.NET core</PackageTags>
<PackageProjectUrl>https://github.com/ThreeMammals/Ocelot.Provider.Consul</PackageProjectUrl>
<PackageProjectUrl>https://github.com/ThreeMammals/Ocelot.Provider.Consul</PackageProjectUrl>
<PackageIconUrl>http://threemammals.com/images/ocelot_logo.png</PackageIconUrl>
<RuntimeIdentifiers>win10-x64;osx.10.11-x64;osx.10.12-x64;win7-x64</RuntimeIdentifiers>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<Authors>Tom Pallister</Authors>
<CodeAnalysisRuleSet>..\..\codeanalysis.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<DebugType>full</DebugType>
<DebugSymbols>True</DebugSymbols>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Ocelot\Ocelot.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Consul" Version="0.7.2.6" />
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.164">
<PrivateAssets>all</PrivateAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<PackageReference Update="Microsoft.SourceLink.GitHub" Version="1.0.0" />
</ItemGroup>
</Project>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
<NoPackageAnalysis>true</NoPackageAnalysis>
<Description>Provides Ocelot extensions to use Consul</Description>
<AssemblyTitle>Ocelot.Provider.Consul</AssemblyTitle>
<VersionPrefix>0.0.0-dev</VersionPrefix>
<AssemblyName>Ocelot.Provider.Consul</AssemblyName>
<PackageId>Ocelot.Provider.Consul</PackageId>
<PackageTags>API Gateway;.NET core</PackageTags>
<PackageProjectUrl>https://github.com/ThreeMammals/Ocelot.Provider.Consul</PackageProjectUrl>
<PackageProjectUrl>https://github.com/ThreeMammals/Ocelot.Provider.Consul</PackageProjectUrl>
<PackageIconUrl>http://threemammals.com/images/ocelot_logo.png</PackageIconUrl>
<RuntimeIdentifiers>win10-x64;osx.10.11-x64;osx.10.12-x64;win7-x64</RuntimeIdentifiers>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<Authors>Tom Pallister</Authors>
<CodeAnalysisRuleSet>..\..\codeanalysis.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<DebugType>full</DebugType>
<DebugSymbols>True</DebugSymbols>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Ocelot\Ocelot.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Consul" Version="1.6.1.1" />
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.164">
<PrivateAssets>all</PrivateAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<PackageReference Update="Microsoft.SourceLink.GitHub" Version="1.0.0" />
</ItemGroup>
</Project>

View File

@@ -1,35 +1,35 @@
namespace Ocelot.Provider.Eureka
{
using ServiceDiscovery.Providers;
using Steeltoe.Common.Discovery;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Values;
public class Eureka : IServiceDiscoveryProvider
{
private readonly IDiscoveryClient _client;
private readonly string _serviceName;
public Eureka(string serviceName, IDiscoveryClient client)
{
_client = client;
_serviceName = serviceName;
}
public Task<List<Service>> Get()
{
var services = new List<Service>();
var instances = _client.GetInstances(_serviceName);
if (instances != null && instances.Any())
{
services.AddRange(instances.Select(i => new Service(i.ServiceId, new ServiceHostAndPort(i.Host, i.Port, i.Uri.Scheme), "", "", new List<string>())));
}
return Task.FromResult(services);
}
}
}
namespace Ocelot.Provider.Eureka
{
using Ocelot.ServiceDiscovery.Providers;
using Steeltoe.Discovery;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Ocelot.Values;
public class Eureka : IServiceDiscoveryProvider
{
private readonly IDiscoveryClient _client;
private readonly string _serviceName;
public Eureka(string serviceName, IDiscoveryClient client)
{
_client = client;
_serviceName = serviceName;
}
public Task<List<Service>> Get()
{
var services = new List<Service>();
var instances = _client.GetInstances(_serviceName);
if (instances != null && instances.Any())
{
services.AddRange(instances.Select(i => new Service(i.ServiceId, new ServiceHostAndPort(i.Host, i.Port, i.Uri.Scheme), "", "", new List<string>())));
}
return Task.FromResult(services);
}
}
}

View File

@@ -1,21 +1,21 @@
namespace Ocelot.Provider.Eureka
{
using Microsoft.Extensions.DependencyInjection;
using ServiceDiscovery;
using Steeltoe.Common.Discovery;
public static class EurekaProviderFactory
{
public static ServiceDiscoveryFinderDelegate Get = (provider, config, route) =>
{
var client = provider.GetService<IDiscoveryClient>();
if (config.Type?.ToLower() == "eureka" && client != null)
{
return new Eureka(route.ServiceName, client);
}
return null;
};
}
}
namespace Ocelot.Provider.Eureka
{
using Microsoft.Extensions.DependencyInjection;
using Ocelot.ServiceDiscovery;
using Steeltoe.Discovery;
public static class EurekaProviderFactory
{
public static ServiceDiscoveryFinderDelegate Get = (provider, config, route) =>
{
var client = provider.GetService<IDiscoveryClient>();
if (config.Type?.ToLower() == "eureka" && client != null)
{
return new Eureka(route.ServiceName, client);
}
return null;
};
}
}

View File

@@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<TargetFramework>net5.0</TargetFramework>
<NoPackageAnalysis>true</NoPackageAnalysis>
<Description>Provides Ocelot extensions to use Eureka</Description>
<AssemblyTitle>Ocelot.Provider.Eureka</AssemblyTitle>
@@ -27,7 +27,8 @@
<ProjectReference Include="..\Ocelot\Ocelot.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Steeltoe.Discovery.ClientCore" Version="2.4.2" />
<PackageReference Include="Steeltoe.Discovery.ClientCore" Version="3.0.1" />
<PackageReference Include="Steeltoe.Discovery.Eureka" Version="3.0.1" />
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.164">
<PrivateAssets>all</PrivateAssets>
</PackageReference>

View File

@@ -1,43 +1,43 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<NoPackageAnalysis>true</NoPackageAnalysis>
<Product>Ocelot</Product>
<Description>Provides Ocelot extensions to use kubernetes</Description>
<PackageProjectUrl>https://github.com/ThreeMammals/Ocelot</PackageProjectUrl>
<PackageIconUrl>http://threemammals.com/images/ocelot_logo.png</PackageIconUrl>
<PackageReleaseNotes></PackageReleaseNotes>
<AssemblyName>Ocelot.Provider.Kubernetes</AssemblyName>
<PackageId>Ocelot.Provider.Kubernetes</PackageId>
<PackageTags>API Gateway;.NET core</PackageTags>
<RuntimeIdentifiers>win10-x64;osx.10.11-x64;osx.10.12-x64;win7-x64</RuntimeIdentifiers>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<Version>0.0.0-dev</Version>
<Authors>geffzhang</Authors>
<Company />
<CodeAnalysisRuleSet>..\..\codeanalysis.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
<Compile Remove="IKubeApiClientFactory.cs" />
<Compile Remove="KubeApiClientFactory.cs" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="KubeClient" Version="2.3.11" />
<PackageReference Include="KubeClient.Extensions.DependencyInjection" Version="2.3.11" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Ocelot\Ocelot.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Update="Microsoft.SourceLink.GitHub" Version="1.0.0" />
</ItemGroup>
</Project>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
<NoPackageAnalysis>true</NoPackageAnalysis>
<Product>Ocelot</Product>
<Description>Provides Ocelot extensions to use kubernetes</Description>
<PackageProjectUrl>https://github.com/ThreeMammals/Ocelot</PackageProjectUrl>
<PackageIconUrl>http://threemammals.com/images/ocelot_logo.png</PackageIconUrl>
<PackageReleaseNotes></PackageReleaseNotes>
<AssemblyName>Ocelot.Provider.Kubernetes</AssemblyName>
<PackageId>Ocelot.Provider.Kubernetes</PackageId>
<PackageTags>API Gateway;.NET core</PackageTags>
<RuntimeIdentifiers>win10-x64;osx.10.11-x64;osx.10.12-x64;win7-x64</RuntimeIdentifiers>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<Version>0.0.0-dev</Version>
<Authors>geffzhang</Authors>
<Company />
<CodeAnalysisRuleSet>..\..\codeanalysis.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
<Compile Remove="IKubeApiClientFactory.cs" />
<Compile Remove="KubeApiClientFactory.cs" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="KubeClient" Version="2.3.15" />
<PackageReference Include="KubeClient.Extensions.DependencyInjection" Version="2.3.15" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Ocelot\Ocelot.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Update="Microsoft.SourceLink.GitHub" Version="1.0.0" />
</ItemGroup>
</Project>

View File

@@ -1,38 +1,38 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<NoPackageAnalysis>true</NoPackageAnalysis>
<Description>Provides Ocelot extensions to use Polly.NET</Description>
<AssemblyTitle>Ocelot.Provider.Polly</AssemblyTitle>
<VersionPrefix>0.0.0-dev</VersionPrefix>
<AssemblyName>Ocelot.Provider.Polly</AssemblyName>
<PackageId>Ocelot.Provider.Polly</PackageId>
<PackageTags>API Gateway;.NET core</PackageTags>
<PackageProjectUrl>https://github.com/ThreeMammals/Ocelot.Provider.Polly</PackageProjectUrl>
<PackageProjectUrl>https://github.com/ThreeMammals/Ocelot.Provider.Polly</PackageProjectUrl>
<PackageIconUrl>http://threemammals.com/images/ocelot_logo.png</PackageIconUrl>
<RuntimeIdentifiers>win10-x64;osx.10.11-x64;osx.10.12-x64;win7-x64</RuntimeIdentifiers>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<Authors>Tom Pallister</Authors>
<CodeAnalysisRuleSet>..\..\codeanalysis.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<DebugType>full</DebugType>
<DebugSymbols>True</DebugSymbols>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Ocelot\Ocelot.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.164">
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="Polly" Version="7.2.0" />
</ItemGroup>
<ItemGroup>
<PackageReference Update="Microsoft.SourceLink.GitHub" Version="1.0.0" />
</ItemGroup>
</Project>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
<NoPackageAnalysis>true</NoPackageAnalysis>
<Description>Provides Ocelot extensions to use Polly.NET</Description>
<AssemblyTitle>Ocelot.Provider.Polly</AssemblyTitle>
<VersionPrefix>0.0.0-dev</VersionPrefix>
<AssemblyName>Ocelot.Provider.Polly</AssemblyName>
<PackageId>Ocelot.Provider.Polly</PackageId>
<PackageTags>API Gateway;.NET core</PackageTags>
<PackageProjectUrl>https://github.com/ThreeMammals/Ocelot.Provider.Polly</PackageProjectUrl>
<PackageProjectUrl>https://github.com/ThreeMammals/Ocelot.Provider.Polly</PackageProjectUrl>
<PackageIconUrl>http://threemammals.com/images/ocelot_logo.png</PackageIconUrl>
<RuntimeIdentifiers>win10-x64;osx.10.11-x64;osx.10.12-x64;win7-x64</RuntimeIdentifiers>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<Authors>Tom Pallister</Authors>
<CodeAnalysisRuleSet>..\..\codeanalysis.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<DebugType>full</DebugType>
<DebugSymbols>True</DebugSymbols>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Ocelot\Ocelot.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.164">
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="Polly" Version="7.2.1" />
</ItemGroup>
<ItemGroup>
<PackageReference Update="Microsoft.SourceLink.GitHub" Version="1.0.0" />
</ItemGroup>
</Project>

View File

@@ -1,16 +0,0 @@
namespace Ocelot.Provider.Rafty
{
using Newtonsoft.Json;
internal class BearerToken
{
[JsonProperty("access_token")]
public string AccessToken { get; set; }
[JsonProperty("expires_in")]
public int ExpiresIn { get; set; }
[JsonProperty("token_type")]
public string TokenType { get; set; }
}
}

View File

@@ -1,14 +0,0 @@
namespace Ocelot.Provider.Rafty
{
using global::Rafty.FiniteStateMachine;
public class FakeCommand : ICommand
{
public FakeCommand(string value)
{
this.Value = value;
}
public string Value { get; private set; }
}
}

View File

@@ -1,7 +0,0 @@
namespace Ocelot.Provider.Rafty
{
public class FilePeer
{
public string HostAndPort { get; set; }
}
}

View File

@@ -1,14 +0,0 @@
namespace Ocelot.Provider.Rafty
{
using System.Collections.Generic;
public class FilePeers
{
public FilePeers()
{
Peers = new List<FilePeer>();
}
public List<FilePeer> Peers { get; set; }
}
}

View File

@@ -1,44 +0,0 @@
namespace Ocelot.Provider.Rafty
{
using Administration;
using Configuration.Repository;
using global::Rafty.Concensus.Peers;
using global::Rafty.Infrastructure;
using Microsoft.Extensions.Options;
using Middleware;
using System.Collections.Generic;
using System.Net.Http;
public class FilePeersProvider : IPeersProvider
{
private readonly IOptions<FilePeers> _options;
private readonly List<IPeer> _peers;
private IBaseUrlFinder _finder;
private IInternalConfigurationRepository _repo;
private IIdentityServerConfiguration _identityServerConfig;
public FilePeersProvider(IOptions<FilePeers> options, IBaseUrlFinder finder, IInternalConfigurationRepository repo, IIdentityServerConfiguration identityServerConfig)
{
_identityServerConfig = identityServerConfig;
_repo = repo;
_finder = finder;
_options = options;
_peers = new List<IPeer>();
var config = _repo.Get();
foreach (var item in _options.Value.Peers)
{
var httpClient = new HttpClient();
//todo what if this errors?
var httpPeer = new HttpPeer(item.HostAndPort, httpClient, _finder, config.Data, _identityServerConfig);
_peers.Add(httpPeer);
}
}
public List<IPeer> Get()
{
return _peers;
}
}
}

View File

@@ -1,130 +0,0 @@
namespace Ocelot.Provider.Rafty
{
using Administration;
using Configuration;
using global::Rafty.Concensus.Messages;
using global::Rafty.Concensus.Peers;
using global::Rafty.FiniteStateMachine;
using global::Rafty.Infrastructure;
using Middleware;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Threading.Tasks;
public class HttpPeer : IPeer
{
private readonly string _hostAndPort;
private readonly HttpClient _httpClient;
private readonly JsonSerializerSettings _jsonSerializerSettings;
private readonly string _baseSchemeUrlAndPort;
private BearerToken _token;
private readonly IInternalConfiguration _config;
private readonly IIdentityServerConfiguration _identityServerConfiguration;
public HttpPeer(string hostAndPort, HttpClient httpClient, IBaseUrlFinder finder, IInternalConfiguration config, IIdentityServerConfiguration identityServerConfiguration)
{
_identityServerConfiguration = identityServerConfiguration;
_config = config;
Id = hostAndPort;
_hostAndPort = hostAndPort;
_httpClient = httpClient;
_jsonSerializerSettings = new JsonSerializerSettings()
{
TypeNameHandling = TypeNameHandling.All
};
_baseSchemeUrlAndPort = finder.Find();
}
public string Id { get; }
public async Task<RequestVoteResponse> Request(RequestVote requestVote)
{
if (_token == null)
{
await SetToken();
}
var json = JsonConvert.SerializeObject(requestVote, _jsonSerializerSettings);
var content = new StringContent(json);
content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/json");
var response = await _httpClient.PostAsync($"{_hostAndPort}/administration/raft/requestvote", content);
if (response.IsSuccessStatusCode)
{
return JsonConvert.DeserializeObject<RequestVoteResponse>(await response.Content.ReadAsStringAsync(), _jsonSerializerSettings);
}
return new RequestVoteResponse(false, requestVote.Term);
}
public async Task<AppendEntriesResponse> Request(AppendEntries appendEntries)
{
try
{
if (_token == null)
{
await SetToken();
}
var json = JsonConvert.SerializeObject(appendEntries, _jsonSerializerSettings);
var content = new StringContent(json);
content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/json");
var response = await _httpClient.PostAsync($"{_hostAndPort}/administration/raft/appendEntries", content);
if (response.IsSuccessStatusCode)
{
return JsonConvert.DeserializeObject<AppendEntriesResponse>(await response.Content.ReadAsStringAsync(), _jsonSerializerSettings);
}
return new AppendEntriesResponse(appendEntries.Term, false);
}
catch (Exception ex)
{
Console.WriteLine(ex);
return new AppendEntriesResponse(appendEntries.Term, false);
}
}
public async Task<Response<T>> Request<T>(T command)
where T : ICommand
{
Console.WriteLine("SENDING REQUEST....");
if (_token == null)
{
await SetToken();
}
var json = JsonConvert.SerializeObject(command, _jsonSerializerSettings);
var content = new StringContent(json);
content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/json");
var response = await _httpClient.PostAsync($"{_hostAndPort}/administration/raft/command", content);
if (response.IsSuccessStatusCode)
{
Console.WriteLine("REQUEST OK....");
var okResponse = JsonConvert.DeserializeObject<OkResponse<ICommand>>(await response.Content.ReadAsStringAsync(), _jsonSerializerSettings);
return new OkResponse<T>((T)okResponse.Command);
}
Console.WriteLine("REQUEST NOT OK....");
return new ErrorResponse<T>(await response.Content.ReadAsStringAsync(), command);
}
private async Task SetToken()
{
var tokenUrl = $"{_baseSchemeUrlAndPort}{_config.AdministrationPath}/connect/token";
var formData = new List<KeyValuePair<string, string>>
{
new KeyValuePair<string, string>("client_id", _identityServerConfiguration.ApiName),
new KeyValuePair<string, string>("client_secret", _identityServerConfiguration.ApiSecret),
new KeyValuePair<string, string>("scope", _identityServerConfiguration.ApiName),
new KeyValuePair<string, string>("grant_type", "client_credentials")
};
var content = new FormUrlEncodedContent(formData);
var response = await _httpClient.PostAsync(tokenUrl, content);
var responseContent = await response.Content.ReadAsStringAsync();
response.EnsureSuccessStatusCode();
_token = JsonConvert.DeserializeObject<BearerToken>(responseContent);
_httpClient.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue(_token.TokenType, _token.AccessToken);
}
}
}

View File

@@ -1,40 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<NoPackageAnalysis>true</NoPackageAnalysis>
<Description>Provides Ocelot extensions to use Rafty</Description>
<AssemblyTitle>Ocelot.Provider.Rafty</AssemblyTitle>
<VersionPrefix>0.0.0-dev</VersionPrefix>
<AssemblyName>Ocelot.Provider.Rafty</AssemblyName>
<PackageId>Ocelot.Provider.Rafty</PackageId>
<PackageTags>API Gateway;.NET core</PackageTags>
<PackageProjectUrl>https://github.com/ThreeMammals/Ocelot.Provider.Rafty</PackageProjectUrl>
<PackageProjectUrl>https://github.com/ThreeMammals/Ocelot.Provider.Rafty</PackageProjectUrl>
<PackageIconUrl>http://threemammals.com/images/ocelot_logo.png</PackageIconUrl>
<RuntimeIdentifiers>win10-x64;osx.10.11-x64;osx.10.12-x64;win7-x64</RuntimeIdentifiers>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<Authors>Tom Pallister</Authors>
<CodeAnalysisRuleSet>..\..\codeanalysis.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<DebugType>full</DebugType>
<DebugSymbols>True</DebugSymbols>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Ocelot\Ocelot.csproj" />
<ProjectReference Include="..\Ocelot.Administration\Ocelot.Administration.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Data.SQLite" Version="3.1.1" />
<PackageReference Include="Rafty" Version="0.4.4" />
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.164">
<PrivateAssets>all</PrivateAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<PackageReference Update="Microsoft.SourceLink.GitHub" Version="1.0.0" />
</ItemGroup>
</Project>

View File

@@ -1,28 +0,0 @@
namespace Ocelot.Provider.Rafty
{
using Configuration.Setter;
using DependencyInjection;
using global::Rafty.Concensus.Node;
using global::Rafty.FiniteStateMachine;
using global::Rafty.Infrastructure;
using global::Rafty.Log;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
public static class OcelotAdministrationBuilderExtensions
{
public static IOcelotAdministrationBuilder AddRafty(this IOcelotAdministrationBuilder builder)
{
var settings = new InMemorySettings(4000, 6000, 100, 10000);
builder.Services.RemoveAll<IFileConfigurationSetter>();
builder.Services.AddSingleton<IFileConfigurationSetter, RaftyFileConfigurationSetter>();
builder.Services.AddSingleton<ILog, SqlLiteLog>();
builder.Services.AddSingleton<IFiniteStateMachine, OcelotFiniteStateMachine>();
builder.Services.AddSingleton<ISettings>(settings);
builder.Services.AddSingleton<IPeersProvider, FilePeersProvider>();
builder.Services.AddSingleton<INode, Node>();
builder.Services.Configure<FilePeers>(builder.ConfigurationRoot);
return builder;
}
}
}

View File

@@ -1,25 +0,0 @@
namespace Ocelot.Provider.Rafty
{
using Configuration.Setter;
using global::Rafty.FiniteStateMachine;
using global::Rafty.Log;
using System.Threading.Tasks;
public class OcelotFiniteStateMachine : IFiniteStateMachine
{
private readonly IFileConfigurationSetter _setter;
public OcelotFiniteStateMachine(IFileConfigurationSetter setter)
{
_setter = setter;
}
public async Task Handle(LogEntry log)
{
//todo - handle an error
//hack it to just cast as at the moment we know this is the only command :P
var hack = (UpdateFileConfiguration)log.CommandData;
await _setter.Set(hack.Configuration);
}
}
}

View File

@@ -1,18 +0,0 @@
using System.Reflection;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Ocelot")]
[assembly: AssemblyTrademark("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("d6df4206-0dba-41d8-884d-c3e08290fdbb")]

View File

@@ -1,96 +0,0 @@
namespace Ocelot.Provider.Rafty
{
using global::Rafty.Concensus.Messages;
using global::Rafty.Concensus.Node;
using global::Rafty.FiniteStateMachine;
using Logging;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Middleware;
using Newtonsoft.Json;
using System;
using System.IO;
using System.Threading.Tasks;
[Authorize]
[Route("raft")]
public class RaftController : Controller
{
private readonly INode _node;
private readonly IOcelotLogger _logger;
private readonly string _baseSchemeUrlAndPort;
private readonly JsonSerializerSettings _jsonSerialiserSettings;
public RaftController(INode node, IOcelotLoggerFactory loggerFactory, IBaseUrlFinder finder)
{
_jsonSerialiserSettings = new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.All
};
_baseSchemeUrlAndPort = finder.Find();
_logger = loggerFactory.CreateLogger<RaftController>();
_node = node;
}
[Route("appendentries")]
public async Task<IActionResult> AppendEntries()
{
using (var reader = new StreamReader(HttpContext.Request.Body))
{
var json = await reader.ReadToEndAsync();
var appendEntries = JsonConvert.DeserializeObject<AppendEntries>(json, _jsonSerialiserSettings);
_logger.LogDebug($"{_baseSchemeUrlAndPort}/appendentries called, my state is {_node.State.GetType().FullName}");
var appendEntriesResponse = await _node.Handle(appendEntries);
return new OkObjectResult(appendEntriesResponse);
}
}
[Route("requestvote")]
public async Task<IActionResult> RequestVote()
{
using (var reader = new StreamReader(HttpContext.Request.Body))
{
var json = await reader.ReadToEndAsync();
var requestVote = JsonConvert.DeserializeObject<RequestVote>(json, _jsonSerialiserSettings);
_logger.LogDebug($"{_baseSchemeUrlAndPort}/requestvote called, my state is {_node.State.GetType().FullName}");
var requestVoteResponse = await _node.Handle(requestVote);
return new OkObjectResult(requestVoteResponse);
}
}
[Route("command")]
public async Task<IActionResult> Command()
{
try
{
using (var reader = new StreamReader(HttpContext.Request.Body))
{
var json = await reader.ReadToEndAsync();
var command = JsonConvert.DeserializeObject<ICommand>(json, _jsonSerialiserSettings);
_logger.LogDebug($"{_baseSchemeUrlAndPort}/command called, my state is {_node.State.GetType().FullName}");
var commandResponse = await _node.Accept(command);
json = JsonConvert.SerializeObject(commandResponse, _jsonSerialiserSettings);
return StatusCode(200, json);
}
}
catch (Exception e)
{
_logger.LogError($"THERE WAS A PROBLEM ON NODE {_node.State.CurrentState.Id}", e);
throw;
}
}
}
}

View File

@@ -1,30 +0,0 @@
namespace Ocelot.Provider.Rafty
{
using Configuration.File;
using Configuration.Setter;
using global::Rafty.Concensus.Node;
using global::Rafty.Infrastructure;
using System.Threading.Tasks;
public class RaftyFileConfigurationSetter : IFileConfigurationSetter
{
private readonly INode _node;
public RaftyFileConfigurationSetter(INode node)
{
_node = node;
}
public async Task<Responses.Response> Set(FileConfiguration fileConfiguration)
{
var result = await _node.Accept(new UpdateFileConfiguration(fileConfiguration));
if (result.GetType() == typeof(ErrorResponse<UpdateFileConfiguration>))
{
return new Responses.ErrorResponse(new UnableToSaveAcceptCommand($"unable to save file configuration to state machine"));
}
return new Responses.OkResponse();
}
}
}

View File

@@ -1,49 +0,0 @@
namespace Ocelot.Provider.Rafty
{
using global::Rafty.Concensus.Node;
using global::Rafty.Infrastructure;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Middleware;
using System.Threading.Tasks;
public static class RaftyMiddlewareConfigurationProvider
{
public static OcelotMiddlewareConfigurationDelegate Get = builder =>
{
if (UsingRafty(builder))
{
SetUpRafty(builder);
}
return Task.CompletedTask;
};
private static bool UsingRafty(IApplicationBuilder builder)
{
var node = builder.ApplicationServices.GetService<INode>();
if (node != null)
{
return true;
}
return false;
}
private static void SetUpRafty(IApplicationBuilder builder)
{
var applicationLifetime = builder.ApplicationServices.GetService<IApplicationLifetime>();
applicationLifetime.ApplicationStopping.Register(() => OnShutdown(builder));
var node = builder.ApplicationServices.GetService<INode>();
var nodeId = builder.ApplicationServices.GetService<NodeId>();
node.Start(nodeId);
}
private static void OnShutdown(IApplicationBuilder app)
{
var node = app.ApplicationServices.GetService<INode>();
node.Stop();
}
}
}

View File

@@ -1,334 +0,0 @@
namespace Ocelot.Provider.Rafty
{
using global::Rafty.Infrastructure;
using global::Rafty.Log;
using Microsoft.Data.Sqlite;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
public class SqlLiteLog : ILog
{
private readonly string _path;
private readonly SemaphoreSlim _sempaphore = new SemaphoreSlim(1, 1);
private readonly ILogger _logger;
private readonly NodeId _nodeId;
public SqlLiteLog(NodeId nodeId, ILoggerFactory loggerFactory)
{
_logger = loggerFactory.CreateLogger<SqlLiteLog>();
_nodeId = nodeId;
_path = $"{nodeId.Id.Replace("/", "").Replace(":", "")}.db";
_sempaphore.Wait();
if (!File.Exists(_path))
{
var fs = File.Create(_path);
fs.Dispose();
using (var connection = new SqliteConnection($"Data Source={_path};"))
{
connection.Open();
const string sql = @"create table logs (
id integer primary key,
data text not null
)";
using (var command = new SqliteCommand(sql, connection))
{
var result = command.ExecuteNonQuery();
_logger.LogInformation(result == 0
? $"id: {_nodeId.Id} create database, result: {result}"
: $"id: {_nodeId.Id} did not create database., result: {result}");
}
}
}
_sempaphore.Release();
}
public async Task<int> LastLogIndex()
{
_sempaphore.Wait();
var result = 1;
using (var connection = new SqliteConnection($"Data Source={_path};"))
{
connection.Open();
var sql = @"select id from logs order by id desc limit 1";
using (var command = new SqliteCommand(sql, connection))
{
var index = Convert.ToInt32(await command.ExecuteScalarAsync());
if (index > result)
{
result = index;
}
}
}
_sempaphore.Release();
return result;
}
public async Task<long> LastLogTerm()
{
_sempaphore.Wait();
long result = 0;
using (var connection = new SqliteConnection($"Data Source={_path};"))
{
connection.Open();
var sql = @"select data from logs order by id desc limit 1";
using (var command = new SqliteCommand(sql, connection))
{
var data = Convert.ToString(await command.ExecuteScalarAsync());
var jsonSerializerSettings = new JsonSerializerSettings()
{
TypeNameHandling = TypeNameHandling.All
};
var log = JsonConvert.DeserializeObject<LogEntry>(data, jsonSerializerSettings);
if (log != null && log.Term > result)
{
result = log.Term;
}
}
}
_sempaphore.Release();
return result;
}
public async Task<int> Count()
{
_sempaphore.Wait();
var result = 0;
using (var connection = new SqliteConnection($"Data Source={_path};"))
{
connection.Open();
var sql = @"select count(id) from logs";
using (var command = new SqliteCommand(sql, connection))
{
var index = Convert.ToInt32(await command.ExecuteScalarAsync());
if (index > result)
{
result = index;
}
}
}
_sempaphore.Release();
return result;
}
public async Task<int> Apply(LogEntry log)
{
_sempaphore.Wait();
using (var connection = new SqliteConnection($"Data Source={_path};"))
{
connection.Open();
var jsonSerializerSettings = new JsonSerializerSettings()
{
TypeNameHandling = TypeNameHandling.All
};
var data = JsonConvert.SerializeObject(log, jsonSerializerSettings);
//todo - sql injection dont copy this..
var sql = $"insert into logs (data) values ('{data}')";
_logger.LogInformation($"id: {_nodeId.Id}, sql: {sql}");
using (var command = new SqliteCommand(sql, connection))
{
var result = await command.ExecuteNonQueryAsync();
_logger.LogInformation($"id: {_nodeId.Id}, insert log result: {result}");
}
sql = "select last_insert_rowid()";
using (var command = new SqliteCommand(sql, connection))
{
var result = await command.ExecuteScalarAsync();
_logger.LogInformation($"id: {_nodeId.Id}, about to release semaphore");
_sempaphore.Release();
_logger.LogInformation($"id: {_nodeId.Id}, saved log to sqlite");
return Convert.ToInt32(result);
}
}
}
public async Task DeleteConflictsFromThisLog(int index, LogEntry logEntry)
{
_sempaphore.Wait();
using (var connection = new SqliteConnection($"Data Source={_path};"))
{
connection.Open();
//todo - sql injection dont copy this..
var sql = $"select data from logs where id = {index};";
_logger.LogInformation($"id: {_nodeId.Id} sql: {sql}");
using (var command = new SqliteCommand(sql, connection))
{
var data = Convert.ToString(await command.ExecuteScalarAsync());
var jsonSerializerSettings = new JsonSerializerSettings()
{
TypeNameHandling = TypeNameHandling.All
};
_logger.LogInformation($"id {_nodeId.Id} got log for index: {index}, data is {data} and new log term is {logEntry.Term}");
var log = JsonConvert.DeserializeObject<LogEntry>(data, jsonSerializerSettings);
if (logEntry != null && log != null && logEntry.Term != log.Term)
{
//todo - sql injection dont copy this..
var deleteSql = $"delete from logs where id >= {index};";
_logger.LogInformation($"id: {_nodeId.Id} sql: {deleteSql}");
using (var deleteCommand = new SqliteCommand(deleteSql, connection))
{
var result = await deleteCommand.ExecuteNonQueryAsync();
}
}
}
}
_sempaphore.Release();
}
public async Task<bool> IsDuplicate(int index, LogEntry logEntry)
{
_sempaphore.Wait();
using (var connection = new SqliteConnection($"Data Source={_path};"))
{
connection.Open();
//todo - sql injection dont copy this..
var sql = $"select data from logs where id = {index};";
using (var command = new SqliteCommand(sql, connection))
{
var data = Convert.ToString(await command.ExecuteScalarAsync());
var jsonSerializerSettings = new JsonSerializerSettings()
{
TypeNameHandling = TypeNameHandling.All
};
var log = JsonConvert.DeserializeObject<LogEntry>(data, jsonSerializerSettings);
if (logEntry != null && log != null && logEntry.Term == log.Term)
{
_sempaphore.Release();
return true;
}
}
}
_sempaphore.Release();
return false;
}
public async Task<LogEntry> Get(int index)
{
_sempaphore.Wait();
using (var connection = new SqliteConnection($"Data Source={_path};"))
{
connection.Open();
//todo - sql injection dont copy this..
var sql = $"select data from logs where id = {index}";
using (var command = new SqliteCommand(sql, connection))
{
var data = Convert.ToString(await command.ExecuteScalarAsync());
var jsonSerializerSettings = new JsonSerializerSettings()
{
TypeNameHandling = TypeNameHandling.All
};
var log = JsonConvert.DeserializeObject<LogEntry>(data, jsonSerializerSettings);
_sempaphore.Release();
return log;
}
}
}
public async Task<List<(int index, LogEntry logEntry)>> GetFrom(int index)
{
_sempaphore.Wait();
var logsToReturn = new List<(int, LogEntry)>();
using (var connection = new SqliteConnection($"Data Source={_path};"))
{
connection.Open();
//todo - sql injection dont copy this..
var sql = $"select id, data from logs where id >= {index}";
using (var command = new SqliteCommand(sql, connection))
{
using (var reader = await command.ExecuteReaderAsync())
{
while (reader.Read())
{
var id = Convert.ToInt32(reader[0]);
var data = (string)reader[1];
var jsonSerializerSettings = new JsonSerializerSettings()
{
TypeNameHandling = TypeNameHandling.All
};
var log = JsonConvert.DeserializeObject<LogEntry>(data, jsonSerializerSettings);
logsToReturn.Add((id, log));
}
}
}
_sempaphore.Release();
return logsToReturn;
}
}
public async Task<long> GetTermAtIndex(int index)
{
_sempaphore.Wait();
long result = 0;
using (var connection = new SqliteConnection($"Data Source={_path};"))
{
connection.Open();
//todo - sql injection dont copy this..
var sql = $"select data from logs where id = {index}";
using (var command = new SqliteCommand(sql, connection))
{
var data = Convert.ToString(await command.ExecuteScalarAsync());
var jsonSerializerSettings = new JsonSerializerSettings()
{
TypeNameHandling = TypeNameHandling.All
};
var log = JsonConvert.DeserializeObject<LogEntry>(data, jsonSerializerSettings);
if (log != null && log.Term > result)
{
result = log.Term;
}
}
}
_sempaphore.Release();
return result;
}
public async Task Remove(int indexOfCommand)
{
_sempaphore.Wait();
using (var connection = new SqliteConnection($"Data Source={_path};"))
{
connection.Open();
//todo - sql injection dont copy this..
var deleteSql = $"delete from logs where id >= {indexOfCommand};";
_logger.LogInformation($"id: {_nodeId.Id} Remove {deleteSql}");
using (var deleteCommand = new SqliteCommand(deleteSql, connection))
{
var result = await deleteCommand.ExecuteNonQueryAsync();
}
}
_sempaphore.Release();
}
}
}

View File

@@ -1,12 +0,0 @@
namespace Ocelot.Provider.Rafty
{
using Errors;
public class UnableToSaveAcceptCommand : Error
{
public UnableToSaveAcceptCommand(string message)
: base(message, OcelotErrorCode.UnknownError, 404)
{
}
}
}

View File

@@ -1,15 +0,0 @@
namespace Ocelot.Provider.Rafty
{
using Configuration.File;
using global::Rafty.FiniteStateMachine;
public class UpdateFileConfiguration : ICommand
{
public UpdateFileConfiguration(FileConfiguration configuration)
{
Configuration = configuration;
}
public FileConfiguration Configuration { get; private set; }
}
}

View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<TargetFramework>net5.0</TargetFramework>
<NoPackageAnalysis>true</NoPackageAnalysis>
<Description>This package provides methods to integrate Butterfly tracing with Ocelot.</Description>
<AssemblyTitle>Ocelot.Tracing.Butterfly</AssemblyTitle>

View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<TargetFramework>net5.0</TargetFramework>
<Version>0.0.0-dev</Version>
<Authors>Kjell-Åke Gafvelin</Authors>
<Description>This package provides OpenTracing support to Ocelot.</Description>

View File

@@ -1,13 +0,0 @@
namespace Ocelot.Authorisation
{
using Ocelot.Errors;
using System.Net;
public class ClaimValueNotAuthorisedError : Error
{
public ClaimValueNotAuthorisedError(string message)
: base(message, OcelotErrorCode.ClaimValueNotAuthorisedError, 403)
{
}
}
}

View File

@@ -1,12 +0,0 @@
namespace Ocelot.Authorisation.Middleware
{
using Microsoft.AspNetCore.Builder;
public static class AuthorisationMiddlewareMiddlewareExtensions
{
public static IApplicationBuilder UseAuthorisationMiddleware(this IApplicationBuilder builder)
{
return builder.UseMiddleware<AuthorisationMiddleware>();
}
}
}

View File

@@ -1,12 +0,0 @@
namespace Ocelot.Authorisation
{
using Ocelot.Errors;
public class ScopeNotAuthorisedError : Error
{
public ScopeNotAuthorisedError(string message)
: base(message, OcelotErrorCode.ScopeNotAuthorisedError, 403)
{
}
}
}

View File

@@ -0,0 +1,13 @@
namespace Ocelot.Authorization
{
using Ocelot.Errors;
using System.Net;
public class ClaimValueNotAuthorizedError : Error
{
public ClaimValueNotAuthorizedError(string message)
: base(message, OcelotErrorCode.ClaimValueNotAuthorizedError, 403)
{
}
}
}

View File

@@ -1,4 +1,4 @@
namespace Ocelot.Authorisation
namespace Ocelot.Authorization
{
using Ocelot.Infrastructure.Claims.Parser;
using Ocelot.DownstreamRouteFinder.UrlMatcher;
@@ -8,16 +8,16 @@
using System.Security.Claims;
using System.Text.RegularExpressions;
public class ClaimsAuthoriser : IClaimsAuthoriser
public class ClaimsAuthorizer : IClaimsAuthorizer
{
private readonly IClaimsParser _claimsParser;
public ClaimsAuthoriser(IClaimsParser claimsParser)
public ClaimsAuthorizer(IClaimsParser claimsParser)
{
_claimsParser = claimsParser;
}
public Response<bool> Authorise(
public Response<bool> Authorize(
ClaimsPrincipal claimsPrincipal,
Dictionary<string, string> routeClaimsRequirement,
List<PlaceholderNameAndValue> urlPathPlaceholderNameAndValues
@@ -45,10 +45,10 @@
{
// match
var actualValue = matchingPlaceholders[0].Value;
var authorised = values.Data.Contains(actualValue);
if (!authorised)
var authorized = values.Data.Contains(actualValue);
if (!authorized)
{
return new ErrorResponse<bool>(new ClaimValueNotAuthorisedError(
return new ErrorResponse<bool>(new ClaimValueNotAuthorizedError(
$"dynamic claim value for {variableName} of {string.Join(", ", values.Data)} is not the same as required value: {actualValue}"));
}
}
@@ -57,12 +57,12 @@
// config error
if (matchingPlaceholders.Length == 0)
{
return new ErrorResponse<bool>(new ClaimValueNotAuthorisedError(
return new ErrorResponse<bool>(new ClaimValueNotAuthorizedError(
$"config error: requires variable claim value: {variableName} placeholders does not contain that variable: {string.Join(", ", urlPathPlaceholderNameAndValues.Select(p => p.Name))}"));
}
else
{
return new ErrorResponse<bool>(new ClaimValueNotAuthorisedError(
return new ErrorResponse<bool>(new ClaimValueNotAuthorizedError(
$"config error: requires variable claim value: {required.Value} but placeholders are ambiguous: {string.Join(", ", urlPathPlaceholderNameAndValues.Where(p => p.Name.Equals(variableName)).Select(p => p.Value))}"));
}
}
@@ -70,10 +70,10 @@
else
{
// static claim
var authorised = values.Data.Contains(required.Value);
if (!authorised)
var authorized = values.Data.Contains(required.Value);
if (!authorized)
{
return new ErrorResponse<bool>(new ClaimValueNotAuthorisedError(
return new ErrorResponse<bool>(new ClaimValueNotAuthorizedError(
$"claim value: {string.Join(", ", values.Data)} is not the same as required value: {required.Value} for type: {required.Key}"));
}
}

View File

@@ -2,16 +2,16 @@
using Ocelot.Responses;
using System.Security.Claims;
namespace Ocelot.Authorisation
namespace Ocelot.Authorization
{
using System.Collections.Generic;
public interface IClaimsAuthoriser
public interface IClaimsAuthorizer
{
Response<bool> Authorise(
Response<bool> Authorize(
ClaimsPrincipal claimsPrincipal,
Dictionary<string, string> routeClaimsRequirement,
List<PlaceholderNameAndValue> urlPathPlaceholderNameAndValues
List<PlaceholderNameAndValue> urlPathPlaceholderNameAndValues
);
}
}
}

View File

@@ -1,12 +1,12 @@
using Ocelot.Responses;
using System.Security.Claims;
namespace Ocelot.Authorisation
namespace Ocelot.Authorization
{
using System.Collections.Generic;
public interface IScopesAuthoriser
public interface IScopesAuthorizer
{
Response<bool> Authorise(ClaimsPrincipal claimsPrincipal, List<string> routeAllowedScopes);
Response<bool> Authorize(ClaimsPrincipal claimsPrincipal, List<string> routeAllowedScopes);
}
}
}

View File

@@ -1,4 +1,4 @@
namespace Ocelot.Authorisation.Middleware
namespace Ocelot.Authorization.Middleware
{
using Ocelot.Configuration;
using Ocelot.Logging;
@@ -8,21 +8,21 @@
using Microsoft.AspNetCore.Http;
using Ocelot.DownstreamRouteFinder.Middleware;
public class AuthorisationMiddleware : OcelotMiddleware
public class AuthorizationMiddleware : OcelotMiddleware
{
private readonly RequestDelegate _next;
private readonly IClaimsAuthoriser _claimsAuthoriser;
private readonly IScopesAuthoriser _scopesAuthoriser;
private readonly IClaimsAuthorizer _claimsAuthorizer;
private readonly IScopesAuthorizer _scopesAuthorizer;
public AuthorisationMiddleware(RequestDelegate next,
IClaimsAuthoriser claimsAuthoriser,
IScopesAuthoriser scopesAuthoriser,
public AuthorizationMiddleware(RequestDelegate next,
IClaimsAuthorizer claimsAuthorizer,
IScopesAuthorizer scopesAuthorizer,
IOcelotLoggerFactory loggerFactory)
: base(loggerFactory.CreateLogger<AuthorisationMiddleware>())
: base(loggerFactory.CreateLogger<AuthorizationMiddleware>())
{
_next = next;
_claimsAuthoriser = claimsAuthoriser;
_scopesAuthoriser = scopesAuthoriser;
_claimsAuthorizer = claimsAuthorizer;
_scopesAuthorizer = scopesAuthorizer;
}
public async Task Invoke(HttpContext httpContext)
@@ -33,65 +33,65 @@
{
Logger.LogInformation("route is authenticated scopes must be checked");
var authorised = _scopesAuthoriser.Authorise(httpContext.User, downstreamRoute.AuthenticationOptions.AllowedScopes);
var authorized = _scopesAuthorizer.Authorize(httpContext.User, downstreamRoute.AuthenticationOptions.AllowedScopes);
if (authorised.IsError)
if (authorized.IsError)
{
Logger.LogWarning("error authorising user scopes");
Logger.LogWarning("error authorizing user scopes");
httpContext.Items.UpsertErrors(authorised.Errors);
httpContext.Items.UpsertErrors(authorized.Errors);
return;
}
if (IsAuthorised(authorised))
if (IsAuthorized(authorized))
{
Logger.LogInformation("user scopes is authorised calling next authorisation checks");
Logger.LogInformation("user scopes is authorized calling next authorization checks");
}
else
{
Logger.LogWarning("user scopes is not authorised setting pipeline error");
Logger.LogWarning("user scopes is not authorized setting pipeline error");
httpContext.Items.SetError(new UnauthorisedError(
httpContext.Items.SetError(new UnauthorizedError(
$"{httpContext.User.Identity.Name} unable to access {downstreamRoute.UpstreamPathTemplate.OriginalValue}"));
}
}
if (!IsOptionsHttpMethod(httpContext) && IsAuthorisedRoute(downstreamRoute))
if (!IsOptionsHttpMethod(httpContext) && IsAuthorizedRoute(downstreamRoute))
{
Logger.LogInformation("route is authorised");
Logger.LogInformation("route is authorized");
var authorised = _claimsAuthoriser.Authorise(httpContext.User, downstreamRoute.RouteClaimsRequirement, httpContext.Items.TemplatePlaceholderNameAndValues());
var authorized = _claimsAuthorizer.Authorize(httpContext.User, downstreamRoute.RouteClaimsRequirement, httpContext.Items.TemplatePlaceholderNameAndValues());
if (authorised.IsError)
if (authorized.IsError)
{
Logger.LogWarning($"Error whilst authorising {httpContext.User.Identity.Name}. Setting pipeline error");
Logger.LogWarning($"Error whilst authorizing {httpContext.User.Identity.Name}. Setting pipeline error");
httpContext.Items.UpsertErrors(authorised.Errors);
httpContext.Items.UpsertErrors(authorized.Errors);
return;
}
if (IsAuthorised(authorised))
if (IsAuthorized(authorized))
{
Logger.LogInformation($"{httpContext.User.Identity.Name} has succesfully been authorised for {downstreamRoute.UpstreamPathTemplate.OriginalValue}.");
Logger.LogInformation($"{httpContext.User.Identity.Name} has succesfully been authorized for {downstreamRoute.UpstreamPathTemplate.OriginalValue}.");
await _next.Invoke(httpContext);
}
else
{
Logger.LogWarning($"{httpContext.User.Identity.Name} is not authorised to access {downstreamRoute.UpstreamPathTemplate.OriginalValue}. Setting pipeline error");
Logger.LogWarning($"{httpContext.User.Identity.Name} is not authorized to access {downstreamRoute.UpstreamPathTemplate.OriginalValue}. Setting pipeline error");
httpContext.Items.SetError(new UnauthorisedError($"{httpContext.User.Identity.Name} is not authorised to access {downstreamRoute.UpstreamPathTemplate.OriginalValue}"));
httpContext.Items.SetError(new UnauthorizedError($"{httpContext.User.Identity.Name} is not authorized to access {downstreamRoute.UpstreamPathTemplate.OriginalValue}"));
}
}
else
{
Logger.LogInformation($"{downstreamRoute.DownstreamPathTemplate.Value} route does not require user to be authorised");
Logger.LogInformation($"{downstreamRoute.DownstreamPathTemplate.Value} route does not require user to be authorized");
await _next.Invoke(httpContext);
}
}
private static bool IsAuthorised(Response<bool> authorised)
private static bool IsAuthorized(Response<bool> authorized)
{
return authorised.Data;
return authorized.Data;
}
private static bool IsAuthenticatedRoute(DownstreamRoute route)
@@ -99,9 +99,9 @@
return route.IsAuthenticated;
}
private static bool IsAuthorisedRoute(DownstreamRoute route)
private static bool IsAuthorizedRoute(DownstreamRoute route)
{
return route.IsAuthorised;
return route.IsAuthorized;
}
private static bool IsOptionsHttpMethod(HttpContext httpContext)

View File

@@ -0,0 +1,12 @@
namespace Ocelot.Authorization.Middleware
{
using Microsoft.AspNetCore.Builder;
public static class AuthorizationMiddlewareMiddlewareExtensions
{
public static IApplicationBuilder UseAuthorizationMiddleware(this IApplicationBuilder builder)
{
return builder.UseMiddleware<AuthorizationMiddleware>();
}
}
}

View File

@@ -0,0 +1,12 @@
namespace Ocelot.Authorization
{
using Ocelot.Errors;
public class ScopeNotAuthorizedError : Error
{
public ScopeNotAuthorizedError(string message)
: base(message, OcelotErrorCode.ScopeNotAuthorizedError, 403)
{
}
}
}

View File

@@ -1,47 +1,47 @@
using Ocelot.Responses;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
namespace Ocelot.Authorisation
{
using Infrastructure.Claims.Parser;
public class ScopesAuthoriser : IScopesAuthoriser
{
private readonly IClaimsParser _claimsParser;
private readonly string _scope = "scope";
public ScopesAuthoriser(IClaimsParser claimsParser)
{
_claimsParser = claimsParser;
}
public Response<bool> Authorise(ClaimsPrincipal claimsPrincipal, List<string> routeAllowedScopes)
{
if (routeAllowedScopes == null || routeAllowedScopes.Count == 0)
{
return new OkResponse<bool>(true);
}
var values = _claimsParser.GetValuesByClaimType(claimsPrincipal.Claims, _scope);
if (values.IsError)
{
return new ErrorResponse<bool>(values.Errors);
}
var userScopes = values.Data;
var matchesScopes = routeAllowedScopes.Intersect(userScopes).ToList();
if (matchesScopes.Count == 0)
{
return new ErrorResponse<bool>(
new ScopeNotAuthorisedError($"no one user scope: '{string.Join(",", userScopes)}' match with some allowed scope: '{string.Join(",", routeAllowedScopes)}'"));
}
return new OkResponse<bool>(true);
}
}
}
using Ocelot.Responses;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
namespace Ocelot.Authorization
{
using Infrastructure.Claims.Parser;
public class ScopesAuthorizer : IScopesAuthorizer
{
private readonly IClaimsParser _claimsParser;
private readonly string _scope = "scope";
public ScopesAuthorizer(IClaimsParser claimsParser)
{
_claimsParser = claimsParser;
}
public Response<bool> Authorize(ClaimsPrincipal claimsPrincipal, List<string> routeAllowedScopes)
{
if (routeAllowedScopes == null || routeAllowedScopes.Count == 0)
{
return new OkResponse<bool>(true);
}
var values = _claimsParser.GetValuesByClaimType(claimsPrincipal.Claims, _scope);
if (values.IsError)
{
return new ErrorResponse<bool>(values.Errors);
}
var userScopes = values.Data;
var matchesScopes = routeAllowedScopes.Intersect(userScopes).ToList();
if (matchesScopes.Count == 0)
{
return new ErrorResponse<bool>(
new ScopeNotAuthorizedError($"no one user scope: '{string.Join(",", userScopes)}' match with some allowed scope: '{string.Join(",", routeAllowedScopes)}'"));
}
return new OkResponse<bool>(true);
}
}
}

View File

@@ -1,10 +1,10 @@
namespace Ocelot.Authorisation
namespace Ocelot.Authorization
{
using Ocelot.Errors;
public class UnauthorisedError : Error
public class UnauthorizedError : Error
{
public UnauthorisedError(string message)
public UnauthorizedError(string message)
: base(message, OcelotErrorCode.UnauthorizedError, 403)
{
}

View File

@@ -1,12 +1,12 @@
namespace Ocelot.Authorisation
{
namespace Ocelot.Authorization
{
using Ocelot.Errors;
public class UserDoesNotHaveClaimError : Error
{
public UserDoesNotHaveClaimError(string message)
public UserDoesNotHaveClaimError(string message)
: base(message, OcelotErrorCode.UserDoesNotHaveClaimError, 403)
{
}
}
}
}

View File

@@ -18,7 +18,7 @@ namespace Ocelot.Configuration.Builder
private List<ClaimToThing> _claimsToHeaders;
private List<ClaimToThing> _claimToClaims;
private Dictionary<string, string> _routeClaimRequirement;
private bool _isAuthorised;
private bool _isAuthorized;
private List<ClaimToThing> _claimToQueries;
private List<ClaimToThing> _claimToDownstreamPath;
private string _requestIdHeaderKey;
@@ -101,9 +101,9 @@ namespace Ocelot.Configuration.Builder
return this;
}
public DownstreamRouteBuilder WithIsAuthorised(bool input)
public DownstreamRouteBuilder WithIsAuthorized(bool input)
{
_isAuthorised = input;
_isAuthorized = input;
return this;
}
@@ -289,7 +289,7 @@ namespace Ocelot.Configuration.Builder
_claimToClaims,
_claimToDownstreamPath,
_isAuthenticated,
_isAuthorised,
_isAuthorized,
_authenticationOptions,
new DownstreamPathTemplate(_downstreamPathTemplate),
_loadBalancerKey,

View File

@@ -3,7 +3,7 @@ namespace Ocelot.Configuration.Builder
public class RouteOptionsBuilder
{
private bool _isAuthenticated;
private bool _isAuthorised;
private bool _isAuthorized;
private bool _isCached;
private bool _enableRateLimiting;
private bool _useServiceDiscovery;
@@ -20,9 +20,9 @@ namespace Ocelot.Configuration.Builder
return this;
}
public RouteOptionsBuilder WithIsAuthorised(bool isAuthorised)
public RouteOptionsBuilder WithIsAuthorized(bool isAuthorized)
{
_isAuthorised = isAuthorised;
_isAuthorized = isAuthorized;
return this;
}
@@ -40,7 +40,7 @@ namespace Ocelot.Configuration.Builder
public RouteOptions Build()
{
return new RouteOptions(_isAuthenticated, _isAuthorised, _isCached, _enableRateLimiting, _useServiceDiscovery);
return new RouteOptions(_isAuthenticated, _isAuthorized, _isCached, _enableRateLimiting, _useServiceDiscovery);
}
}
}

View File

@@ -1,6 +1,6 @@
namespace Ocelot.Configuration.Creator
{
using Ocelot.Configuration.Builder;
{
using Ocelot.Configuration.Builder;
using Ocelot.Configuration.File;
public class RouteOptionsCreator : IRouteOptionsCreator
@@ -8,14 +8,14 @@ namespace Ocelot.Configuration.Creator
public RouteOptions Create(FileRoute fileRoute)
{
var isAuthenticated = IsAuthenticated(fileRoute);
var isAuthorised = IsAuthorised(fileRoute);
var isAuthorized = IsAuthorized(fileRoute);
var isCached = IsCached(fileRoute);
var enableRateLimiting = IsEnableRateLimiting(fileRoute);
var useServiceDiscovery = !string.IsNullOrEmpty(fileRoute.ServiceName);
var options = new RouteOptionsBuilder()
.WithIsAuthenticated(isAuthenticated)
.WithIsAuthorised(isAuthorised)
.WithIsAuthorized(isAuthorized)
.WithIsCached(isCached)
.WithRateLimiting(enableRateLimiting)
.WithUseServiceDiscovery(useServiceDiscovery)
@@ -34,7 +34,7 @@ namespace Ocelot.Configuration.Creator
return !string.IsNullOrEmpty(fileRoute.AuthenticationOptions?.AuthenticationProviderKey);
}
private bool IsAuthorised(FileRoute fileRoute)
private bool IsAuthorized(FileRoute fileRoute)
{
return fileRoute.RouteClaimsRequirement?.Count > 0;
}

View File

@@ -119,7 +119,7 @@ namespace Ocelot.Configuration.Creator
.WithClaimsToHeaders(claimsToHeaders)
.WithClaimsToClaims(claimsToClaims)
.WithRouteClaimsRequirement(fileRoute.RouteClaimsRequirement)
.WithIsAuthorised(fileRouteOptions.IsAuthorised)
.WithIsAuthorized(fileRouteOptions.IsAuthorized)
.WithClaimsToQueries(claimsToQueries)
.WithClaimsToDownstreamPath(claimsToDownstreamPath)
.WithRequestIdKey(requestIdKey)

View File

@@ -31,7 +31,7 @@ namespace Ocelot.Configuration
List<ClaimToThing> claimsToClaims,
List<ClaimToThing> claimsToPath,
bool isAuthenticated,
bool isAuthorised,
bool isAuthorized,
AuthenticationOptions authenticationOptions,
DownstreamPathTemplate downstreamPathTemplate,
string loadBalancerKey,
@@ -69,7 +69,7 @@ namespace Ocelot.Configuration
ClaimsToClaims = claimsToClaims ?? new List<ClaimToThing>();
ClaimsToPath = claimsToPath ?? new List<ClaimToThing>();
IsAuthenticated = isAuthenticated;
IsAuthorised = isAuthorised;
IsAuthorized = isAuthorized;
AuthenticationOptions = authenticationOptions;
DownstreamPathTemplate = downstreamPathTemplate;
LoadBalancerKey = loadBalancerKey;
@@ -102,7 +102,7 @@ namespace Ocelot.Configuration
public List<ClaimToThing> ClaimsToClaims { get; }
public List<ClaimToThing> ClaimsToPath { get; }
public bool IsAuthenticated { get; }
public bool IsAuthorised { get; }
public bool IsAuthorized { get; }
public AuthenticationOptions AuthenticationOptions { get; }
public DownstreamPathTemplate DownstreamPathTemplate { get; }
public string LoadBalancerKey { get; }

View File

@@ -2,17 +2,17 @@ namespace Ocelot.Configuration
{
public class RouteOptions
{
public RouteOptions(bool isAuthenticated, bool isAuthorised, bool isCached, bool isEnableRateLimiting, bool useServiceDiscovery)
public RouteOptions(bool isAuthenticated, bool isAuthorized, bool isCached, bool isEnableRateLimiting, bool useServiceDiscovery)
{
IsAuthenticated = isAuthenticated;
IsAuthorised = isAuthorised;
IsAuthorized = isAuthorized;
IsCached = isCached;
EnableRateLimiting = isEnableRateLimiting;
UseServiceDiscovery = useServiceDiscovery;
}
public bool IsAuthenticated { get; private set; }
public bool IsAuthorised { get; private set; }
public bool IsAuthorized { get; private set; }
public bool IsCached { get; private set; }
public bool EnableRateLimiting { get; private set; }
public bool UseServiceDiscovery { get; private set; }

View File

@@ -5,7 +5,7 @@ namespace Ocelot.DependencyInjection
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Options;
using Ocelot.Authorisation;
using Ocelot.Authorization;
using Ocelot.Cache;
using Ocelot.Claims;
using Ocelot.Configuration;
@@ -96,8 +96,8 @@ namespace Ocelot.DependencyInjection
Services.TryAddSingleton<IOcelotLoggerFactory, AspDotNetLoggerFactory>();
Services.TryAddSingleton<IRemoveOutputHeaders, RemoveOutputHeaders>();
Services.TryAddSingleton<IClaimToThingConfigurationParser, ClaimToThingConfigurationParser>();
Services.TryAddSingleton<IClaimsAuthoriser, ClaimsAuthoriser>();
Services.TryAddSingleton<IScopesAuthoriser, ScopesAuthoriser>();
Services.TryAddSingleton<IClaimsAuthorizer, ClaimsAuthorizer>();
Services.TryAddSingleton<IScopesAuthorizer, ScopesAuthorizer>();
Services.TryAddSingleton<IAddClaimsToRequest, AddClaimsToRequest>();
Services.TryAddSingleton<IAddHeadersToRequest, AddHeadersToRequest>();
Services.TryAddSingleton<IAddQueriesToRequest, AddQueriesToRequest>();

View File

@@ -16,8 +16,8 @@
NoInstructionsError = 11,
InstructionNotForClaimsError = 12,
UnauthorizedError = 13,
ClaimValueNotAuthorisedError = 14,
ScopeNotAuthorisedError = 15,
ClaimValueNotAuthorizedError = 14,
ScopeNotAuthorizedError = 15,
UserDoesNotHaveClaimError = 16,
DownstreamPathTemplateContainsSchemeError = 17,
DownstreamPathNullOrEmptyError = 18,

View File

@@ -39,22 +39,22 @@
public Func<HttpContext, Func<Task>, Task> AuthenticationMiddleware { get; set; }
/// <summary>
/// This is to allow the user to run any extra authorisation before the Ocelot authentication
/// This is to allow the user to run any extra authorization before the Ocelot authentication
/// kicks in
/// </summary>
/// <value>
/// <placeholder>This is to allow the user to run any extra authorisation before the Ocelot authentication
/// <placeholder>This is to allow the user to run any extra authorization before the Ocelot authentication
/// kicks in</placeholder>
/// </value>
public Func<HttpContext, Func<Task>, Task> PreAuthorisationMiddleware { get; set; }
public Func<HttpContext, Func<Task>, Task> PreAuthorizationMiddleware { get; set; }
/// <summary>
/// This allows the user to completely override the ocelot authorisation middleware
/// This allows the user to completely override the ocelot authorization middleware
/// </summary>
/// <value>
/// <placeholder>This allows the user to completely override the ocelot authorisation middleware</placeholder>
/// <placeholder>This allows the user to completely override the ocelot authorization middleware</placeholder>
/// </value>
public Func<HttpContext, Func<Task>, Task> AuthorisationMiddleware { get; set; }
public Func<HttpContext, Func<Task>, Task> AuthorizationMiddleware { get; set; }
/// <summary>
/// This allows the user to implement there own query string manipulation logic

View File

@@ -8,7 +8,7 @@
using Ocelot.Responder.Middleware;
using Ocelot.Security.Middleware;
using Ocelot.Authentication.Middleware;
using Ocelot.Authorisation.Middleware;
using Ocelot.Authorization.Middleware;
using Ocelot.Cache.Middleware;
using Ocelot.Claims.Middleware;
using Ocelot.DownstreamRouteFinder.Middleware;
@@ -102,23 +102,23 @@
app.Use(pipelineConfiguration.AuthenticationMiddleware);
}
// The next thing we do is look at any claims transforms in case this is important for authorisation
// The next thing we do is look at any claims transforms in case this is important for authorization
app.UseClaimsToClaimsMiddleware();
// Allow pre authorisation logic. The idea being people might want to run something custom before what is built in.
app.UseIfNotNull(pipelineConfiguration.PreAuthorisationMiddleware);
// Allow pre authorization logic. The idea being people might want to run something custom before what is built in.
app.UseIfNotNull(pipelineConfiguration.PreAuthorizationMiddleware);
// Now we have authenticated and done any claims transformation we
// can authorise the request
// can authorize the request
// We allow the ocelot middleware to be overriden by whatever the
// user wants
if (pipelineConfiguration.AuthorisationMiddleware == null)
if (pipelineConfiguration.AuthorizationMiddleware == null)
{
app.UseAuthorisationMiddleware();
app.UseAuthorizationMiddleware();
}
else
{
app.Use(pipelineConfiguration.AuthorisationMiddleware);
app.Use(pipelineConfiguration.AuthorizationMiddleware);
}
// Now we can run the claims to headers transformation middleware

View File

@@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<TargetFramework>net5.0</TargetFramework>
<NoPackageAnalysis>true</NoPackageAnalysis>
<Description>Ocelot is an API Gateway. The project is aimed at people using .NET running a micro services / service orientated architecture that need a unified point of entry into their system. In particular I want easy integration with IdentityServer reference and bearer tokens. reference tokens. Ocelot is a bunch of middlewares in a specific order. Ocelot manipulates the HttpRequest object into a state specified by its configuration until it reaches a request builder middleware where it creates a HttpRequestMessage object which is used to make a request to a downstream service. The middleware that makes the request is the last thing in the Ocelot pipeline. It does not call the next middleware. The response from the downstream service is stored in a per request scoped repository and retrived as the requests goes back up the Ocelot pipeline. There is a piece of middleware that maps the HttpResponseMessage onto the HttpResponse object and that is returned to the client. That is basically it with a bunch of other features.</Description>
<AssemblyTitle>Ocelot</AssemblyTitle>
@@ -24,12 +24,12 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="FluentValidation" Version="8.6.2" />
<PackageReference Include="Microsoft.AspNetCore.MiddlewareAnalysis" Version="3.1.3" />
<PackageReference Include="Microsoft.Extensions.DiagnosticAdapter" Version="3.1.3">
<PackageReference Include="FluentValidation" Version="9.3.0" />
<PackageReference Include="Microsoft.AspNetCore.MiddlewareAnalysis" Version="5.0.0" />
<PackageReference Include="Microsoft.Extensions.DiagnosticAdapter" Version="3.1.10">
<NoWarn>NU1701</NoWarn>
</PackageReference>
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="3.1.3" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="5.0.0" />
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.164">
<PrivateAssets>all</PrivateAssets>
</PackageReference>

View File

@@ -14,8 +14,8 @@ namespace Ocelot.Responder
}
if (errors.Any(e => e.Code == OcelotErrorCode.UnauthorizedError
|| e.Code == OcelotErrorCode.ClaimValueNotAuthorisedError
|| e.Code == OcelotErrorCode.ScopeNotAuthorisedError
|| e.Code == OcelotErrorCode.ClaimValueNotAuthorizedError
|| e.Code == OcelotErrorCode.ScopeNotAuthorizedError
|| e.Code == OcelotErrorCode.UserDoesNotHaveClaimError
|| e.Code == OcelotErrorCode.CannotFindClaimError))
{

View File

@@ -1,22 +1,22 @@
using Ocelot.Errors;
using System.Collections.Generic;
namespace Ocelot.Responses
{
public abstract class Response
{
protected Response()
{
Errors = new List<Error>();
}
protected Response(List<Error> errors)
{
Errors = errors ?? new List<Error>();
using Ocelot.Errors;
using System.Collections.Generic;
namespace Ocelot.Responses
{
public abstract class Response
{
protected Response()
{
Errors = new List<Error>();
}
public List<Error> Errors { get; }
public bool IsError => Errors.Count > 0;
}
protected Response(List<Error> errors)
{
Errors = errors ?? new List<Error>();
}
public List<Error> Errors { get; }
public bool IsError => Errors.Count > 0;
}
}