Incremental work on secure endpoints

This commit is contained in:
Sipke Schoorstra 2022-08-27 21:58:22 +02:00
parent ecfdbac7d0
commit 27cfe7eb91
10 changed files with 95 additions and 18 deletions

View file

@ -15,7 +15,6 @@
<ProjectReference Include="..\..\modules\Elsa.ProtoActor\Elsa.ProtoActor.csproj" />
<ProjectReference Include="..\..\modules\Elsa.Tokens.Api\Elsa.Tokens.Api.csproj" />
<ProjectReference Include="..\Elsa\Elsa.csproj" />
<ProjectReference Include="..\..\modules\Elsa.AspNetCore\Elsa.AspNetCore.csproj" />
<ProjectReference Include="..\..\modules\Elsa.Hangfire\Elsa.Hangfire.csproj" />
<ProjectReference Include="..\..\modules\Elsa.Http\Elsa.Http.csproj" />
<ProjectReference Include="..\..\modules\Elsa.Labels.EntityFrameworkCore.Sqlite\Elsa.Labels.EntityFrameworkCore.Sqlite.csproj" />

View file

@ -1,3 +1,7 @@
using System.Globalization;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using Elsa;
using Elsa.ActivityDefinitions.EntityFrameworkCore.Extensions;
using Elsa.ActivityDefinitions.EntityFrameworkCore.Sqlite;
using Elsa.Extensions;
@ -26,10 +30,14 @@ using Elsa.Workflows.Persistence.Extensions;
using Elsa.Workflows.Runtime.Extensions;
using Elsa.WorkflowServer.Web.Jobs;
using FastEndpoints;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
var builder = WebApplication.CreateBuilder(args);
var services = builder.Services;
EndpointSecurityOptions.DisableSecurity();
// Add Elsa services.
services
.AddElsa(elsa => elsa
@ -64,7 +72,32 @@ services.AddFastEndpoints();
services.AddHealthChecks();
services.AddCors(cors => cors.AddDefaultPolicy(policy => policy.AllowAnyHeader().AllowAnyMethod().AllowAnyOrigin()));
// Authorization policies.
// Authentication & Authorization.
services
.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, options =>
{
var claims =
options.TokenValidationParameters = new TokenValidationParameters
{
IssuerSigningKeyValidator = (key, token, parameters) => true,
ValidateIssuerSigningKey = false,
ValidateAudience = false,
ValidateIssuer = false,
ValidateTokenReplay = false,
ValidateActor = false,
RoleClaimType = ClaimTypes.Role,
TokenReplayValidator = (time, token, parameters) => true,
SignatureValidator = (token, parameters) =>
{
return new JwtSecurityToken(token);
},
};
options.SecurityTokenValidators.Clear();
options.SecurityTokenValidators.Add(new CustomValidator());
});
services.AddAuthorization(options => options.AddPolicy("WorkflowManagerPolicy", policy => policy.RequireAuthenticatedUser()));
// Configure middleware pipeline.
@ -101,11 +134,35 @@ app.MapHealthChecks("/");
app.UseAuthentication();
app.UseAuthorization();
// Register Elsa middleware.
app.UseElsaFastEndpoints();
app.UseJsonSerializationErrorHandler();
app.UseHttpActivities();
// Run.
app.Run();
app.Run();
public class CustomValidator : ISecurityTokenValidator
{
private readonly JwtSecurityTokenHandler _tokenHandler;
public CustomValidator()
{
_tokenHandler = new JwtSecurityTokenHandler();
}
public bool CanReadToken(string securityToken)
{
return true;
}
public ClaimsPrincipal ValidateToken(string securityToken, TokenValidationParameters validationParameters, out SecurityToken validatedToken)
{
var principal = _tokenHandler.ValidateToken(securityToken, validationParameters, out validatedToken);
return principal;
}
public bool CanValidateToken => true;
public int MaximumTokenSizeInBytes { get; set; } = TokenValidationParameters.DefaultMaximumTokenSizeInBytes;
}

View file

@ -1,9 +1,9 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Default": "Debug",
"Microsoft.EntityFrameworkCore": "Warning",
"Microsoft.AspNetCore": "Warning"
"Microsoft.AspNetCore": "Debug"
}
},
"AllowedHosts": "*"

View file

@ -0,0 +1,13 @@
using FastEndpoints;
namespace Elsa;
public static class EndpointSecurityOptions
{
public static string AdminRoleName = "Admin";
public static string ReaderRoleName = "Reader";
public static string WriteRoleName = "Writer";
public static bool SecurityIsEnabled = true;
public static void DisableSecurity() => SecurityIsEnabled = false;
}

View file

@ -14,15 +14,15 @@
<ItemGroup>
<PackageReference Include="EFCore.BulkExtensions" Version="6.4.2" />
<PackageReference Include="LinqKit" Version="1.2.2" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="6.0.3" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="6.0.3" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="6.0.8" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="6.0.8" />
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="6.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="6.0.3" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="6.0.3">
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="6.0.8" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="6.0.8">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="6.0.3" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="6.0.8" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Design" Version="1.1.6" />
<PackageReference Include="Open.Linq.AsyncExtensions" Version="1.2.0" />
</ItemGroup>

View file

@ -7,7 +7,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="6.0.3">
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="6.0.8">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>

View file

@ -7,7 +7,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="6.0.3">
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="6.0.8">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>

View file

@ -18,9 +18,17 @@ public class List : EndpointWithoutRequest<Response>
public override void Configure()
{
Policies(Constants.PolicyName);
Roles("Admin");
Permissions("all", "list:activity-descriptors");
Get("/descriptors/activities");
if (!EndpointSecurityOptions.SecurityIsEnabled)
{
AllowAnonymous();
}
else
{
Roles("Admin", "Reader");
Permissions("*", "list:activity-descriptors");
}
}
public override Task<Response> ExecuteAsync(CancellationToken cancellationToken)

View file

@ -17,7 +17,7 @@ public class List : EndpointWithoutRequest<Response>
public override void Configure()
{
Get("/descriptors/activities");
Get("/descriptors/storage-drivers");
Policies(Constants.PolicyName);
Permissions("all", "read:storage-drivers");
}

View file

@ -7,7 +7,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="6.0.3">
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="6.0.8">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>