From b4d363ea2003340a222bdc817e88c78febf2cf61 Mon Sep 17 00:00:00 2001 From: Richard Garcia Date: Sat, 28 Mar 2026 17:48:17 -0300 Subject: [PATCH 01/21] feat: this commit introduces initial solution and project files for proxy project --- .../Proxy/HttpsRichardy.Federation.Proxy.sln | 39 +++++++++++++++++++ .../HttpsRichardy.Federation.Proxy.csproj | 13 +++++++ 2 files changed, 52 insertions(+) create mode 100644 Applications/Proxy/HttpsRichardy.Federation.Proxy.sln create mode 100644 Applications/Proxy/Source/HttpsRichardy.Federation.Proxy.csproj diff --git a/Applications/Proxy/HttpsRichardy.Federation.Proxy.sln b/Applications/Proxy/HttpsRichardy.Federation.Proxy.sln new file mode 100644 index 0000000..f7ee75b --- /dev/null +++ b/Applications/Proxy/HttpsRichardy.Federation.Proxy.sln @@ -0,0 +1,39 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.31903.59 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Source", "Source", "{B8EFCA5F-814F-285C-A8CB-F00F14650265}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HttpsRichardy.Federation.Proxy", "Source\HttpsRichardy.Federation.Proxy.csproj", "{5D5AAD1B-A3F6-46D9-B7A3-A4627DED1E64}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {5D5AAD1B-A3F6-46D9-B7A3-A4627DED1E64}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5D5AAD1B-A3F6-46D9-B7A3-A4627DED1E64}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5D5AAD1B-A3F6-46D9-B7A3-A4627DED1E64}.Debug|x64.ActiveCfg = Debug|Any CPU + {5D5AAD1B-A3F6-46D9-B7A3-A4627DED1E64}.Debug|x64.Build.0 = Debug|Any CPU + {5D5AAD1B-A3F6-46D9-B7A3-A4627DED1E64}.Debug|x86.ActiveCfg = Debug|Any CPU + {5D5AAD1B-A3F6-46D9-B7A3-A4627DED1E64}.Debug|x86.Build.0 = Debug|Any CPU + {5D5AAD1B-A3F6-46D9-B7A3-A4627DED1E64}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5D5AAD1B-A3F6-46D9-B7A3-A4627DED1E64}.Release|Any CPU.Build.0 = Release|Any CPU + {5D5AAD1B-A3F6-46D9-B7A3-A4627DED1E64}.Release|x64.ActiveCfg = Release|Any CPU + {5D5AAD1B-A3F6-46D9-B7A3-A4627DED1E64}.Release|x64.Build.0 = Release|Any CPU + {5D5AAD1B-A3F6-46D9-B7A3-A4627DED1E64}.Release|x86.ActiveCfg = Release|Any CPU + {5D5AAD1B-A3F6-46D9-B7A3-A4627DED1E64}.Release|x86.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {5D5AAD1B-A3F6-46D9-B7A3-A4627DED1E64} = {B8EFCA5F-814F-285C-A8CB-F00F14650265} + EndGlobalSection +EndGlobal diff --git a/Applications/Proxy/Source/HttpsRichardy.Federation.Proxy.csproj b/Applications/Proxy/Source/HttpsRichardy.Federation.Proxy.csproj new file mode 100644 index 0000000..6e13ddb --- /dev/null +++ b/Applications/Proxy/Source/HttpsRichardy.Federation.Proxy.csproj @@ -0,0 +1,13 @@ + + + + net10.0 + enable + enable + + + + + + + From 9bdbff4fa865ddc8b2b212c09035b0f9b1a91b3c Mon Sep 17 00:00:00 2001 From: Richard Garcia Date: Sat, 28 Mar 2026 17:48:36 -0300 Subject: [PATCH 02/21] feat: this commit introduces launchSettings and appsettings configuration files for proxy project --- .../Source/Properties/launchSettings.json | 23 +++++++++++++++++++ Applications/Proxy/Source/appsettings.json | 9 ++++++++ 2 files changed, 32 insertions(+) create mode 100644 Applications/Proxy/Source/Properties/launchSettings.json create mode 100644 Applications/Proxy/Source/appsettings.json diff --git a/Applications/Proxy/Source/Properties/launchSettings.json b/Applications/Proxy/Source/Properties/launchSettings.json new file mode 100644 index 0000000..14d34bc --- /dev/null +++ b/Applications/Proxy/Source/Properties/launchSettings.json @@ -0,0 +1,23 @@ +{ + "$schema": "https://json.schemastore.org/launchsettings.json", + "profiles": { + "http": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": false, + "applicationUrl": "http://localhost:5239", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "https": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": false, + "applicationUrl": "https://localhost:7292;http://localhost:5239", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git a/Applications/Proxy/Source/appsettings.json b/Applications/Proxy/Source/appsettings.json new file mode 100644 index 0000000..10f68b8 --- /dev/null +++ b/Applications/Proxy/Source/appsettings.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*" +} From f158f30ed7c749a3538501c93e773e185a1ae400 Mon Sep 17 00:00:00 2001 From: Richard Garcia Date: Sat, 28 Mar 2026 17:48:56 -0300 Subject: [PATCH 03/21] feat: this commit introduces initial program.cs file for proxy application setup --- Applications/Proxy/Source/Program.cs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 Applications/Proxy/Source/Program.cs diff --git a/Applications/Proxy/Source/Program.cs b/Applications/Proxy/Source/Program.cs new file mode 100644 index 0000000..691d773 --- /dev/null +++ b/Applications/Proxy/Source/Program.cs @@ -0,0 +1,19 @@ +namespace HttpsRichardy.Federation.Proxy; + +internal static class Program +{ + private static async Task Main(string[] args) + { + var builder = WebApplication.CreateBuilder(args); + + builder.Services.AddAuthorization(); + builder.Services.AddOpenApi(); + + var app = builder.Build(); + + app.UseHttpsRedirection(); + app.UseAuthorization(); + + await app.RunAsync(); + } +} From 91f795ff2ebc21f69d44e6b65afe54ede1559ed2 Mon Sep 17 00:00:00 2001 From: Richard Garcia Date: Sat, 28 Mar 2026 17:51:00 -0300 Subject: [PATCH 04/21] fix: correct target framework version from net10.0 to net9.0 in project file --- Applications/Proxy/Source/HttpsRichardy.Federation.Proxy.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Applications/Proxy/Source/HttpsRichardy.Federation.Proxy.csproj b/Applications/Proxy/Source/HttpsRichardy.Federation.Proxy.csproj index 6e13ddb..e87228a 100644 --- a/Applications/Proxy/Source/HttpsRichardy.Federation.Proxy.csproj +++ b/Applications/Proxy/Source/HttpsRichardy.Federation.Proxy.csproj @@ -1,7 +1,7 @@ - net10.0 + net9.0 enable enable From 26efe76f02ef5ef47039d12ee4e51e42dc92594d Mon Sep 17 00:00:00 2001 From: Richard Garcia Date: Sat, 28 Mar 2026 17:52:00 -0300 Subject: [PATCH 05/21] feat: this commit introduces ocelot package reference for API gateway functionality --- Applications/Proxy/Source/HttpsRichardy.Federation.Proxy.csproj | 1 + 1 file changed, 1 insertion(+) diff --git a/Applications/Proxy/Source/HttpsRichardy.Federation.Proxy.csproj b/Applications/Proxy/Source/HttpsRichardy.Federation.Proxy.csproj index e87228a..090b7fd 100644 --- a/Applications/Proxy/Source/HttpsRichardy.Federation.Proxy.csproj +++ b/Applications/Proxy/Source/HttpsRichardy.Federation.Proxy.csproj @@ -8,6 +8,7 @@ + From 7a8e66e2b82f2d8380dd0279ec615b8727bb10d5 Mon Sep 17 00:00:00 2001 From: Richard Garcia Date: Sat, 28 Mar 2026 18:16:55 -0300 Subject: [PATCH 06/21] feat: this commit introduces global usings --- Applications/Proxy/Source/Usings.cs | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 Applications/Proxy/Source/Usings.cs diff --git a/Applications/Proxy/Source/Usings.cs b/Applications/Proxy/Source/Usings.cs new file mode 100644 index 0000000..2729402 --- /dev/null +++ b/Applications/Proxy/Source/Usings.cs @@ -0,0 +1,2 @@ +global using Ocelot.DependencyInjection; +global using Ocelot.Middleware; From 3736f8e0df6f019f3e4cd6553107de2794d7acac Mon Sep 17 00:00:00 2001 From: Richard Garcia Date: Sat, 28 Mar 2026 18:17:06 -0300 Subject: [PATCH 07/21] fix: remove unnecessary Microsoft.AspNetCore.OpenApi package reference from project file --- Applications/Proxy/Source/HttpsRichardy.Federation.Proxy.csproj | 1 - 1 file changed, 1 deletion(-) diff --git a/Applications/Proxy/Source/HttpsRichardy.Federation.Proxy.csproj b/Applications/Proxy/Source/HttpsRichardy.Federation.Proxy.csproj index 090b7fd..866a7fa 100644 --- a/Applications/Proxy/Source/HttpsRichardy.Federation.Proxy.csproj +++ b/Applications/Proxy/Source/HttpsRichardy.Federation.Proxy.csproj @@ -7,7 +7,6 @@ - From f4b25900c1a5ab90af4f6498e0165fd70e731ad7 Mon Sep 17 00:00:00 2001 From: Richard Garcia Date: Sat, 28 Mar 2026 18:17:25 -0300 Subject: [PATCH 08/21] feat: configure ocelot for api gateway functionality in Program.cs --- Applications/Proxy/Source/Program.cs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Applications/Proxy/Source/Program.cs b/Applications/Proxy/Source/Program.cs index 691d773..0aa08b6 100644 --- a/Applications/Proxy/Source/Program.cs +++ b/Applications/Proxy/Source/Program.cs @@ -6,14 +6,16 @@ private static async Task Main(string[] args) { var builder = WebApplication.CreateBuilder(args); - builder.Services.AddAuthorization(); - builder.Services.AddOpenApi(); + builder.Configuration.AddJsonFile("ocelot.json", optional: false, reloadOnChange: true); + builder.Configuration.AddEnvironmentVariables(); + + builder.Services.AddOcelot(builder.Configuration); var app = builder.Build(); app.UseHttpsRedirection(); - app.UseAuthorization(); + await app.UseOcelot(); await app.RunAsync(); } } From ce769ce2d8695c012803407c2f16634fc6e6423d Mon Sep 17 00:00:00 2001 From: Richard Garcia Date: Sat, 28 Mar 2026 18:17:43 -0300 Subject: [PATCH 09/21] feat: this commit introduces ocelot configuration for identity authentication route --- Applications/Proxy/Source/ocelot.json | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 Applications/Proxy/Source/ocelot.json diff --git a/Applications/Proxy/Source/ocelot.json b/Applications/Proxy/Source/ocelot.json new file mode 100644 index 0000000..3da0000 --- /dev/null +++ b/Applications/Proxy/Source/ocelot.json @@ -0,0 +1,17 @@ +{ + "Routes": [ + { + "UpstreamPathTemplate": "/api/v1/identity/authenticate", + "UpstreamHttpMethod": [ "POST" ], + + "DownstreamPathTemplate": "/api/v1/identity/authenticate", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "{DOWNSTREAM_HOST}", + "Port": 443 + } + ] + } + ] +} \ No newline at end of file From 358437ca741f75910ca40fc7b10f9bc59b8441b7 Mon Sep 17 00:00:00 2001 From: Richard Garcia Date: Sat, 28 Mar 2026 18:48:29 -0300 Subject: [PATCH 10/21] feat: this commit introduces ocelot.provider.polly global using for resilience features --- Applications/Proxy/Source/Usings.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/Applications/Proxy/Source/Usings.cs b/Applications/Proxy/Source/Usings.cs index 2729402..c9e4fae 100644 --- a/Applications/Proxy/Source/Usings.cs +++ b/Applications/Proxy/Source/Usings.cs @@ -1,2 +1,3 @@ global using Ocelot.DependencyInjection; global using Ocelot.Middleware; +global using Ocelot.Provider.Polly; From 2b5577c89befd3e03f051af900a0bee18b9ff221 Mon Sep 17 00:00:00 2001 From: Richard Garcia Date: Sat, 28 Mar 2026 18:48:45 -0300 Subject: [PATCH 11/21] feat: this commit introduces Ocelot.Provider.Polly package reference for resilience features --- Applications/Proxy/Source/HttpsRichardy.Federation.Proxy.csproj | 1 + 1 file changed, 1 insertion(+) diff --git a/Applications/Proxy/Source/HttpsRichardy.Federation.Proxy.csproj b/Applications/Proxy/Source/HttpsRichardy.Federation.Proxy.csproj index 866a7fa..a1cf3e7 100644 --- a/Applications/Proxy/Source/HttpsRichardy.Federation.Proxy.csproj +++ b/Applications/Proxy/Source/HttpsRichardy.Federation.Proxy.csproj @@ -8,6 +8,7 @@ + From 4c63b854d10b216b06da9ad8f6970374d7306474 Mon Sep 17 00:00:00 2001 From: Richard Garcia Date: Sat, 28 Mar 2026 18:48:53 -0300 Subject: [PATCH 12/21] feat: update ocelot configuration to include global settings and rate limiting options --- Applications/Proxy/Source/ocelot.json | 39 ++++++++++++++++++--------- 1 file changed, 26 insertions(+), 13 deletions(-) diff --git a/Applications/Proxy/Source/ocelot.json b/Applications/Proxy/Source/ocelot.json index 3da0000..b46a6f2 100644 --- a/Applications/Proxy/Source/ocelot.json +++ b/Applications/Proxy/Source/ocelot.json @@ -1,17 +1,30 @@ { - "Routes": [ - { - "UpstreamPathTemplate": "/api/v1/identity/authenticate", - "UpstreamHttpMethod": [ "POST" ], - - "DownstreamPathTemplate": "/api/v1/identity/authenticate", - "DownstreamScheme": "http", - "DownstreamHostAndPorts": [ + "GlobalConfiguration": { + "DownstreamScheme": "{GlobalConfiguration__DownstreamScheme}", + "DownstreamHostAndPorts": [ + { + "Host": "{GlobalConfiguration__DownstreamHostAndPorts__0__Host}", + "Port": 5286 + } + ] + }, + "Routes": [ { - "Host": "{DOWNSTREAM_HOST}", - "Port": 443 + "UpstreamPathTemplate": "/api/v1/identity/authenticate", + "DownstreamPathTemplate": "/api/v1/identity/authenticate", + "UpstreamHttpMethod": [ + "POST" + ], + "RateLimitOptions": { + "EnableRateLimiting": true, + "Period": "1s", + "Limit": 5 + }, + "QoSOptions": { + "ExceptionsAllowedBeforeBreaking": 3, + "DurationOfBreak": 5000, + "TimeoutValue": 2000 + } } - ] - } - ] + ] } \ No newline at end of file From 72d050ddb40ebdd5503f98993f48a5b4ef797348 Mon Sep 17 00:00:00 2001 From: Richard Garcia Date: Sat, 28 Mar 2026 18:49:02 -0300 Subject: [PATCH 13/21] feat: enhance ocelot service registration with Polly for resilience features --- Applications/Proxy/Source/Program.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Applications/Proxy/Source/Program.cs b/Applications/Proxy/Source/Program.cs index 0aa08b6..7fa466e 100644 --- a/Applications/Proxy/Source/Program.cs +++ b/Applications/Proxy/Source/Program.cs @@ -9,7 +9,9 @@ private static async Task Main(string[] args) builder.Configuration.AddJsonFile("ocelot.json", optional: false, reloadOnChange: true); builder.Configuration.AddEnvironmentVariables(); - builder.Services.AddOcelot(builder.Configuration); + builder.Services + .AddOcelot(builder.Configuration) + .AddPolly(); var app = builder.Build(); From 0c2ebe17baeac3980e013a2f6fc9faeb05ab08a8 Mon Sep 17 00:00:00 2001 From: Richard Garcia Date: Sat, 28 Mar 2026 18:49:53 -0300 Subject: [PATCH 14/21] feat: update ocelot configuration with fixed downstream scheme and host settings --- Applications/Proxy/Source/ocelot.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Applications/Proxy/Source/ocelot.json b/Applications/Proxy/Source/ocelot.json index b46a6f2..f22cfbb 100644 --- a/Applications/Proxy/Source/ocelot.json +++ b/Applications/Proxy/Source/ocelot.json @@ -1,10 +1,10 @@ { "GlobalConfiguration": { - "DownstreamScheme": "{GlobalConfiguration__DownstreamScheme}", + "DownstreamScheme": "https", "DownstreamHostAndPorts": [ { - "Host": "{GlobalConfiguration__DownstreamHostAndPorts__0__Host}", - "Port": 5286 + "Host": "localhost", + "Port": 8080 } ] }, From fbd75f9d1a2bfc0096d46914f468763306a3724f Mon Sep 17 00:00:00 2001 From: Richard Garcia Date: Sat, 28 Mar 2026 18:51:26 -0300 Subject: [PATCH 15/21] feat: remove unused applications directory --- Applications/.gitkeep | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 Applications/.gitkeep diff --git a/Applications/.gitkeep b/Applications/.gitkeep deleted file mode 100644 index e69de29..0000000 From 8046f07b1845c2a934edea1cce75bb22c9e3abc1 Mon Sep 17 00:00:00 2001 From: Richard Garcia Date: Sat, 28 Mar 2026 18:54:45 -0300 Subject: [PATCH 16/21] feat: this commit introduces .env.example configuration for downstream settings --- Applications/Proxy/.env.example | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 Applications/Proxy/.env.example diff --git a/Applications/Proxy/.env.example b/Applications/Proxy/.env.example new file mode 100644 index 0000000..1f0babd --- /dev/null +++ b/Applications/Proxy/.env.example @@ -0,0 +1,3 @@ +GlobalConfiguration__DownstreamScheme=http +GlobalConfiguration__DownstreamHostAndPorts__0__Host=localhost +GlobalConfiguration__DownstreamHostAndPorts__0__Port=443 \ No newline at end of file From b995e0fc10812d84148730968536df74d1fe066e Mon Sep 17 00:00:00 2001 From: Richard Garcia Date: Sat, 28 Mar 2026 18:55:10 -0300 Subject: [PATCH 17/21] feat: this commit introduces dockerfile and .dockerignore for proxy application --- Applications/Proxy/.dockerignore | 25 +++++++++++++++++++ Applications/Proxy/Dockerfile | 42 ++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+) create mode 100644 Applications/Proxy/.dockerignore create mode 100644 Applications/Proxy/Dockerfile diff --git a/Applications/Proxy/.dockerignore b/Applications/Proxy/.dockerignore new file mode 100644 index 0000000..d3b72df --- /dev/null +++ b/Applications/Proxy/.dockerignore @@ -0,0 +1,25 @@ +**/.vs +**/.git + +**/bin +**/obj +**/.vscode +**/TestResults + +**/appsettings.json +**/appsettings.Development.json +**/appsettings.*.json + +.env +.env.* +.env.example + +*.user +*.suo +*.userosscache +*.sln.docstates +.gitattributes + +Dockerfile +README.md +LICENSE diff --git a/Applications/Proxy/Dockerfile b/Applications/Proxy/Dockerfile new file mode 100644 index 0000000..e12dbf9 --- /dev/null +++ b/Applications/Proxy/Dockerfile @@ -0,0 +1,42 @@ +# use ASP.NET Core 9.0 runtime image (alpine) as base +FROM mcr.microsoft.com/dotnet/aspnet:9.0-alpine AS base +WORKDIR /artifacts +EXPOSE 8080 + +# use SDK image (Alpine) for build +FROM mcr.microsoft.com/dotnet/sdk:9.0-alpine AS build +WORKDIR /workdir + +ARG BUILD_CONFIGURATION=Release +ARG SOLUTION=HttpsRichardy.Federation.Proxy + +# copy only csproj and sln to restore as early as possible +COPY ["Source/${SOLUTION}.WebApi/${SOLUTION}.WebApi.csproj", "${SOLUTION}.WebApi/"] +COPY ["${SOLUTION}.sln", "./"] + +# restore dependencies +RUN dotnet restore "${SOLUTION}.WebApi/${SOLUTION}.WebApi.csproj" + +# copy the rest of the source code +COPY Source/ ./Source/ + +WORKDIR "/workdir/Source/${SOLUTION}.WebApi" + +# build in Release mode +RUN dotnet build "${SOLUTION}.WebApi.csproj" -c $BUILD_CONFIGURATION -o /artifacts/build + +# publish the project for production +RUN dotnet publish "${SOLUTION}.WebApi.csproj" -c $BUILD_CONFIGURATION -o /artifacts/publish /p:UseAppHost=false + +# final image to run the app +FROM base AS final +WORKDIR /artifacts + +ENV ASPNETCORE_URLS=http://+:8080 +ENV DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=true +ENV DOTNET_RUNNING_IN_CONTAINER=true + +# copy published files from the build stage +COPY --from=build /artifacts/publish . + +ENTRYPOINT ["dotnet", "HttpsRichardy.Federation.Proxy.WebApi.dll"] From fd2509e1206b9661969c19350b14ee81ad113a3a Mon Sep 17 00:00:00 2001 From: Richard Garcia Date: Sat, 28 Mar 2026 19:04:56 -0300 Subject: [PATCH 18/21] feat: update Dockerfile and .dockerignore for simplified project structure and improved build process --- Applications/Proxy/.dockerignore | 2 -- Applications/Proxy/Dockerfile | 12 ++++++------ 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/Applications/Proxy/.dockerignore b/Applications/Proxy/.dockerignore index d3b72df..9f620df 100644 --- a/Applications/Proxy/.dockerignore +++ b/Applications/Proxy/.dockerignore @@ -6,9 +6,7 @@ **/.vscode **/TestResults -**/appsettings.json **/appsettings.Development.json -**/appsettings.*.json .env .env.* diff --git a/Applications/Proxy/Dockerfile b/Applications/Proxy/Dockerfile index e12dbf9..287a66c 100644 --- a/Applications/Proxy/Dockerfile +++ b/Applications/Proxy/Dockerfile @@ -11,22 +11,22 @@ ARG BUILD_CONFIGURATION=Release ARG SOLUTION=HttpsRichardy.Federation.Proxy # copy only csproj and sln to restore as early as possible -COPY ["Source/${SOLUTION}.WebApi/${SOLUTION}.WebApi.csproj", "${SOLUTION}.WebApi/"] +COPY ["Source/${SOLUTION}.csproj", "Source/"] COPY ["${SOLUTION}.sln", "./"] # restore dependencies -RUN dotnet restore "${SOLUTION}.WebApi/${SOLUTION}.WebApi.csproj" +RUN dotnet restore "Source/${SOLUTION}.csproj" # copy the rest of the source code COPY Source/ ./Source/ -WORKDIR "/workdir/Source/${SOLUTION}.WebApi" +WORKDIR "/workdir/Source" # build in Release mode -RUN dotnet build "${SOLUTION}.WebApi.csproj" -c $BUILD_CONFIGURATION -o /artifacts/build +RUN dotnet build "${SOLUTION}.csproj" -c $BUILD_CONFIGURATION -o /artifacts/build # publish the project for production -RUN dotnet publish "${SOLUTION}.WebApi.csproj" -c $BUILD_CONFIGURATION -o /artifacts/publish /p:UseAppHost=false +RUN dotnet publish "${SOLUTION}.csproj" -c $BUILD_CONFIGURATION -o /artifacts/publish /p:UseAppHost=false # final image to run the app FROM base AS final @@ -39,4 +39,4 @@ ENV DOTNET_RUNNING_IN_CONTAINER=true # copy published files from the build stage COPY --from=build /artifacts/publish . -ENTRYPOINT ["dotnet", "HttpsRichardy.Federation.Proxy.WebApi.dll"] +ENTRYPOINT ["dotnet", "HttpsRichardy.Federation.Proxy.dll"] From 8b785bcbaf42cc803bc5b6b5daaf44d4ce30d1f5 Mon Sep 17 00:00:00 2001 From: Richard Garcia Date: Sat, 28 Mar 2026 19:34:32 -0300 Subject: [PATCH 19/21] feat: update ocelot configuration to use HTTP scheme and change downstream port --- Applications/Proxy/Source/ocelot.json | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/Applications/Proxy/Source/ocelot.json b/Applications/Proxy/Source/ocelot.json index f22cfbb..1d1610f 100644 --- a/Applications/Proxy/Source/ocelot.json +++ b/Applications/Proxy/Source/ocelot.json @@ -1,21 +1,18 @@ { - "GlobalConfiguration": { - "DownstreamScheme": "https", - "DownstreamHostAndPorts": [ - { - "Host": "localhost", - "Port": 8080 - } - ] - }, "Routes": [ { + "UpstreamHttpMethod": [ "POST" ], "UpstreamPathTemplate": "/api/v1/identity/authenticate", "DownstreamPathTemplate": "/api/v1/identity/authenticate", - "UpstreamHttpMethod": [ - "POST" + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "localhost", + "Port": 5286 + } ], "RateLimitOptions": { + "ClientIdHeader": "Client", "EnableRateLimiting": true, "Period": "1s", "Limit": 5 From 08324adc45701501c4c8babc598d6818f9fb0201 Mon Sep 17 00:00:00 2001 From: Richard Garcia Date: Sat, 28 Mar 2026 19:34:38 -0300 Subject: [PATCH 20/21] feat: update .env.example to reflect new routing configuration for proxy application --- Applications/Proxy/.env.example | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Applications/Proxy/.env.example b/Applications/Proxy/.env.example index 1f0babd..26e088a 100644 --- a/Applications/Proxy/.env.example +++ b/Applications/Proxy/.env.example @@ -1,3 +1,3 @@ -GlobalConfiguration__DownstreamScheme=http -GlobalConfiguration__DownstreamHostAndPorts__0__Host=localhost -GlobalConfiguration__DownstreamHostAndPorts__0__Port=443 \ No newline at end of file +Routes__0__DownstreamScheme=http +Routes__0__DownstreamHostAndPorts__0__Host=localhost +Routes__0__DownstreamHostAndPorts__0__Port=5286 \ No newline at end of file From 6082cb325f818e79ca67fa1b55f718adb48c2f5a Mon Sep 17 00:00:00 2001 From: Richard Garcia Date: Sat, 28 Mar 2026 19:40:03 -0300 Subject: [PATCH 21/21] feat: expand ocelot configuration with additional routes and rate limiting options --- Applications/Proxy/Source/ocelot.json | 552 ++++++++++++++++++++++++++ 1 file changed, 552 insertions(+) diff --git a/Applications/Proxy/Source/ocelot.json b/Applications/Proxy/Source/ocelot.json index 1d1610f..d3fa057 100644 --- a/Applications/Proxy/Source/ocelot.json +++ b/Applications/Proxy/Source/ocelot.json @@ -1,5 +1,120 @@ { "Routes": [ + { + "UpstreamHttpMethod": [ "GET" ], + "UpstreamPathTemplate": "/.well-known/openid-configuration", + "DownstreamPathTemplate": "/.well-known/openid-configuration", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "localhost", + "Port": 5286 + } + ], + "RateLimitOptions": { + "ClientIdHeader": "Client", + "EnableRateLimiting": true, + "Period": "1s", + "Limit": 5 + }, + "QoSOptions": { + "ExceptionsAllowedBeforeBreaking": 3, + "DurationOfBreak": 5000, + "TimeoutValue": 2000 + } + }, + { + "UpstreamHttpMethod": [ "GET" ], + "UpstreamPathTemplate": "/.well-known/jwks.json", + "DownstreamPathTemplate": "/.well-known/jwks.json", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "localhost", + "Port": 5286 + } + ], + "RateLimitOptions": { + "ClientIdHeader": "Client", + "EnableRateLimiting": true, + "Period": "1s", + "Limit": 5 + }, + "QoSOptions": { + "ExceptionsAllowedBeforeBreaking": 3, + "DurationOfBreak": 5000, + "TimeoutValue": 2000 + } + }, + { + "UpstreamHttpMethod": [ "POST" ], + "UpstreamPathTemplate": "/api/v1/protocol/open-id/connect/token", + "DownstreamPathTemplate": "/api/v1/protocol/open-id/connect/token", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "localhost", + "Port": 5286 + } + ], + "RateLimitOptions": { + "ClientIdHeader": "Client", + "EnableRateLimiting": true, + "Period": "1s", + "Limit": 5 + }, + "QoSOptions": { + "ExceptionsAllowedBeforeBreaking": 3, + "DurationOfBreak": 5000, + "TimeoutValue": 2000 + } + }, + { + "UpstreamHttpMethod": [ "POST" ], + "UpstreamPathTemplate": "/api/v1/identity", + "DownstreamPathTemplate": "/api/v1/identity", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "localhost", + "Port": 5286 + } + ], + "RateLimitOptions": { + "ClientIdHeader": "Client", + "EnableRateLimiting": true, + "Period": "1s", + "Limit": 5 + }, + "QoSOptions": { + "ExceptionsAllowedBeforeBreaking": 3, + "DurationOfBreak": 5000, + "TimeoutValue": 2000 + } + }, + { + "UpstreamHttpMethod": [ "GET" ], + "UpstreamPathTemplate": "/api/v1/identity/principal", + "DownstreamPathTemplate": "/api/v1/identity/principal", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "localhost", + "Port": 5286 + } + ], + "RateLimitOptions": { + "ClientIdHeader": "Client", + "EnableRateLimiting": true, + "Period": "1s", + "Limit": 5 + }, + "QoSOptions": { + "ExceptionsAllowedBeforeBreaking": 3, + "DurationOfBreak": 5000, + "TimeoutValue": 2000 + } + }, { "UpstreamHttpMethod": [ "POST" ], "UpstreamPathTemplate": "/api/v1/identity/authenticate", @@ -22,6 +137,443 @@ "DurationOfBreak": 5000, "TimeoutValue": 2000 } + }, + { + "UpstreamHttpMethod": [ "POST" ], + "UpstreamPathTemplate": "/api/v1/identity/refresh-token", + "DownstreamPathTemplate": "/api/v1/identity/refresh-token", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "localhost", + "Port": 5286 + } + ], + "RateLimitOptions": { + "ClientIdHeader": "Client", + "EnableRateLimiting": true, + "Period": "1s", + "Limit": 5 + }, + "QoSOptions": { + "ExceptionsAllowedBeforeBreaking": 3, + "DurationOfBreak": 5000, + "TimeoutValue": 2000 + } + }, + { + "UpstreamHttpMethod": [ "POST" ], + "UpstreamPathTemplate": "/api/v1/identity/invalidate-session", + "DownstreamPathTemplate": "/api/v1/identity/invalidate-session", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "localhost", + "Port": 5286 + } + ], + "RateLimitOptions": { + "ClientIdHeader": "Client", + "EnableRateLimiting": true, + "Period": "1s", + "Limit": 5 + }, + "QoSOptions": { + "ExceptionsAllowedBeforeBreaking": 3, + "DurationOfBreak": 5000, + "TimeoutValue": 2000 + } + }, + { + "UpstreamHttpMethod": [ "GET", "POST" ], + "UpstreamPathTemplate": "/api/v1/groups", + "DownstreamPathTemplate": "/api/v1/groups", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "localhost", + "Port": 5286 + } + ], + "RateLimitOptions": { + "ClientIdHeader": "Client", + "EnableRateLimiting": true, + "Period": "1s", + "Limit": 5 + }, + "QoSOptions": { + "ExceptionsAllowedBeforeBreaking": 3, + "DurationOfBreak": 5000, + "TimeoutValue": 2000 + } + }, + { + "UpstreamHttpMethod": [ "PUT", "DELETE" ], + "UpstreamPathTemplate": "/api/v1/groups/{id}", + "DownstreamPathTemplate": "/api/v1/groups/{id}", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "localhost", + "Port": 5286 + } + ], + "RateLimitOptions": { + "ClientIdHeader": "Client", + "EnableRateLimiting": true, + "Period": "1s", + "Limit": 5 + }, + "QoSOptions": { + "ExceptionsAllowedBeforeBreaking": 3, + "DurationOfBreak": 5000, + "TimeoutValue": 2000 + } + }, + { + "UpstreamHttpMethod": [ "GET", "POST" ], + "UpstreamPathTemplate": "/api/v1/groups/{id}/permissions", + "DownstreamPathTemplate": "/api/v1/groups/{id}/permissions", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "localhost", + "Port": 5286 + } + ], + "RateLimitOptions": { + "ClientIdHeader": "Client", + "EnableRateLimiting": true, + "Period": "1s", + "Limit": 5 + }, + "QoSOptions": { + "ExceptionsAllowedBeforeBreaking": 3, + "DurationOfBreak": 5000, + "TimeoutValue": 2000 + } + }, + { + "UpstreamHttpMethod": [ "DELETE" ], + "UpstreamPathTemplate": "/api/v1/groups/{id}/permissions/{permissionId}", + "DownstreamPathTemplate": "/api/v1/groups/{id}/permissions/{permissionId}", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "localhost", + "Port": 5286 + } + ], + "RateLimitOptions": { + "ClientIdHeader": "Client", + "EnableRateLimiting": true, + "Period": "1s", + "Limit": 5 + }, + "QoSOptions": { + "ExceptionsAllowedBeforeBreaking": 3, + "DurationOfBreak": 5000, + "TimeoutValue": 2000 + } + }, + { + "UpstreamHttpMethod": [ "GET", "POST" ], + "UpstreamPathTemplate": "/api/v1/permissions", + "DownstreamPathTemplate": "/api/v1/permissions", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "localhost", + "Port": 5286 + } + ], + "RateLimitOptions": { + "ClientIdHeader": "Client", + "EnableRateLimiting": true, + "Period": "1s", + "Limit": 5 + }, + "QoSOptions": { + "ExceptionsAllowedBeforeBreaking": 3, + "DurationOfBreak": 5000, + "TimeoutValue": 2000 + } + }, + { + "UpstreamHttpMethod": [ "PUT", "DELETE" ], + "UpstreamPathTemplate": "/api/v1/permissions/{id}", + "DownstreamPathTemplate": "/api/v1/permissions/{id}", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "localhost", + "Port": 5286 + } + ], + "RateLimitOptions": { + "ClientIdHeader": "Client", + "EnableRateLimiting": true, + "Period": "1s", + "Limit": 5 + }, + "QoSOptions": { + "ExceptionsAllowedBeforeBreaking": 3, + "DurationOfBreak": 5000, + "TimeoutValue": 2000 + } + }, + { + "UpstreamHttpMethod": [ "GET", "POST" ], + "UpstreamPathTemplate": "/api/v1/realms", + "DownstreamPathTemplate": "/api/v1/realms", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "localhost", + "Port": 5286 + } + ], + "RateLimitOptions": { + "ClientIdHeader": "Client", + "EnableRateLimiting": true, + "Period": "1s", + "Limit": 5 + }, + "QoSOptions": { + "ExceptionsAllowedBeforeBreaking": 3, + "DurationOfBreak": 5000, + "TimeoutValue": 2000 + } + }, + { + "UpstreamHttpMethod": [ "PUT", "DELETE" ], + "UpstreamPathTemplate": "/api/v1/realms/{id}", + "DownstreamPathTemplate": "/api/v1/realms/{id}", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "localhost", + "Port": 5286 + } + ], + "RateLimitOptions": { + "ClientIdHeader": "Client", + "EnableRateLimiting": true, + "Period": "1s", + "Limit": 5 + }, + "QoSOptions": { + "ExceptionsAllowedBeforeBreaking": 3, + "DurationOfBreak": 5000, + "TimeoutValue": 2000 + } + }, + { + "UpstreamHttpMethod": [ "GET", "POST" ], + "UpstreamPathTemplate": "/api/v1/realms/{id}/permissions", + "DownstreamPathTemplate": "/api/v1/realms/{id}/permissions", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "localhost", + "Port": 5286 + } + ], + "RateLimitOptions": { + "ClientIdHeader": "Client", + "EnableRateLimiting": true, + "Period": "1s", + "Limit": 5 + }, + "QoSOptions": { + "ExceptionsAllowedBeforeBreaking": 3, + "DurationOfBreak": 5000, + "TimeoutValue": 2000 + } + }, + { + "UpstreamHttpMethod": [ "DELETE" ], + "UpstreamPathTemplate": "/api/v1/realms/{id}/permissions/{permissionId}", + "DownstreamPathTemplate": "/api/v1/realms/{id}/permissions/{permissionId}", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "localhost", + "Port": 5286 + } + ], + "RateLimitOptions": { + "ClientIdHeader": "Client", + "EnableRateLimiting": true, + "Period": "1s", + "Limit": 5 + }, + "QoSOptions": { + "ExceptionsAllowedBeforeBreaking": 3, + "DurationOfBreak": 5000, + "TimeoutValue": 2000 + } + }, + { + "UpstreamHttpMethod": [ "POST" ], + "UpstreamPathTemplate": "/api/v1/scopes", + "DownstreamPathTemplate": "/api/v1/scopes", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "localhost", + "Port": 5286 + } + ], + "RateLimitOptions": { + "ClientIdHeader": "Client", + "EnableRateLimiting": true, + "Period": "1s", + "Limit": 5 + }, + "QoSOptions": { + "ExceptionsAllowedBeforeBreaking": 3, + "DurationOfBreak": 5000, + "TimeoutValue": 2000 + } + }, + { + "UpstreamHttpMethod": [ "GET" ], + "UpstreamPathTemplate": "/api/v1/users", + "DownstreamPathTemplate": "/api/v1/users", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "localhost", + "Port": 5286 + } + ], + "RateLimitOptions": { + "ClientIdHeader": "Client", + "EnableRateLimiting": true, + "Period": "1s", + "Limit": 5 + }, + "QoSOptions": { + "ExceptionsAllowedBeforeBreaking": 3, + "DurationOfBreak": 5000, + "TimeoutValue": 2000 + } + }, + { + "UpstreamHttpMethod": [ "DELETE" ], + "UpstreamPathTemplate": "/api/v1/users/{id}", + "DownstreamPathTemplate": "/api/v1/users/{id}", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "localhost", + "Port": 5286 + } + ], + "RateLimitOptions": { + "ClientIdHeader": "Client", + "EnableRateLimiting": true, + "Period": "1s", + "Limit": 5 + }, + "QoSOptions": { + "ExceptionsAllowedBeforeBreaking": 3, + "DurationOfBreak": 5000, + "TimeoutValue": 2000 + } + }, + { + "UpstreamHttpMethod": [ "GET", "POST" ], + "UpstreamPathTemplate": "/api/v1/users/{id}/permissions", + "DownstreamPathTemplate": "/api/v1/users/{id}/permissions", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "localhost", + "Port": 5286 + } + ], + "RateLimitOptions": { + "ClientIdHeader": "Client", + "EnableRateLimiting": true, + "Period": "1s", + "Limit": 5 + }, + "QoSOptions": { + "ExceptionsAllowedBeforeBreaking": 3, + "DurationOfBreak": 5000, + "TimeoutValue": 2000 + } + }, + { + "UpstreamHttpMethod": [ "DELETE" ], + "UpstreamPathTemplate": "/api/v1/users/{id}/permissions/{permissionId}", + "DownstreamPathTemplate": "/api/v1/users/{id}/permissions/{permissionId}", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "localhost", + "Port": 5286 + } + ], + "RateLimitOptions": { + "ClientIdHeader": "Client", + "EnableRateLimiting": true, + "Period": "1s", + "Limit": 5 + }, + "QoSOptions": { + "ExceptionsAllowedBeforeBreaking": 3, + "DurationOfBreak": 5000, + "TimeoutValue": 2000 + } + }, + { + "UpstreamHttpMethod": [ "GET", "POST" ], + "UpstreamPathTemplate": "/api/v1/users/{id}/groups", + "DownstreamPathTemplate": "/api/v1/users/{id}/groups", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "localhost", + "Port": 5286 + } + ], + "RateLimitOptions": { + "ClientIdHeader": "Client", + "EnableRateLimiting": true, + "Period": "1s", + "Limit": 5 + }, + "QoSOptions": { + "ExceptionsAllowedBeforeBreaking": 3, + "DurationOfBreak": 5000, + "TimeoutValue": 2000 + } + }, + { + "UpstreamHttpMethod": [ "DELETE" ], + "UpstreamPathTemplate": "/api/v1/users/{id}/groups/{groupId}", + "DownstreamPathTemplate": "/api/v1/users/{id}/groups/{groupId}", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "localhost", + "Port": 5286 + } + ], + "RateLimitOptions": { + "ClientIdHeader": "Client", + "EnableRateLimiting": true, + "Period": "1s", + "Limit": 5 + }, + "QoSOptions": { + "ExceptionsAllowedBeforeBreaking": 3, + "DurationOfBreak": 5000, + "TimeoutValue": 2000 + } } ] } \ No newline at end of file