diff --git a/InvestmentManager/InvestmentManager/InvestmentManager.csproj b/InvestmentManager/InvestmentManager/InvestmentManager.csproj
index 65d9c3c..19d9958 100644
--- a/InvestmentManager/InvestmentManager/InvestmentManager.csproj
+++ b/InvestmentManager/InvestmentManager/InvestmentManager.csproj
@@ -12,6 +12,7 @@
+
diff --git a/InvestmentManager/InvestmentManager/Program.cs b/InvestmentManager/InvestmentManager/Program.cs
index 477c408..a07add4 100644
--- a/InvestmentManager/InvestmentManager/Program.cs
+++ b/InvestmentManager/InvestmentManager/Program.cs
@@ -1,7 +1,9 @@
+using AspNetCoreRateLimit;
using HealthChecks.UI.Client;
using InvestmentManager.Core;
using InvestmentManager.DataAccess.EF;
using InvestmentManager.HealthChecks;
+using InvestmentManager.RateLimit;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Diagnostics.HealthChecks;
using Microsoft.AspNetCore.Http;
@@ -126,6 +128,12 @@
options.AddHealthCheckEndpoint(" HC UI endpoint", "https://localhost:51500/healthui");
}).AddInMemoryStorage();
+// Add and configure services required for AspNetCoreRateLimit
+RateLimit.ConfigureServices(builder.Services, builder.Configuration);
+// This is required to set the default value for AspNetCoreRateLimit.IProcessingStrategy
+builder.Services.AddSingleton();
+
+
var app = builder.Build();
// Configure the HTTP request pipeline.
@@ -144,6 +152,7 @@
app.UseCors();
app.UseAuthentication();
app.UseAuthorization();
+app.UseIpRateLimiting();
app.UseEndpoints(endpoints =>
{
diff --git a/InvestmentManager/InvestmentManager/RateLimit/RateLimit.cs b/InvestmentManager/InvestmentManager/RateLimit/RateLimit.cs
new file mode 100644
index 0000000..04ae75c
--- /dev/null
+++ b/InvestmentManager/InvestmentManager/RateLimit/RateLimit.cs
@@ -0,0 +1,30 @@
+using AspNetCoreRateLimit;
+using Microsoft.AspNetCore.Http;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.DependencyInjection;
+
+namespace InvestmentManager.RateLimit
+{
+ public static class RateLimit
+ {
+ public static void ConfigureServices(IServiceCollection services, IConfiguration configuration)
+ {
+ // needed to load configuration from appsettings.json
+ services.AddOptions();
+ // needed to store rate limit counters and ip rules
+ services.AddMemoryCache();
+ //load general configuration from appsettings.json
+ services.Configure(configuration.GetSection("IpRateLimiting"));
+ //load ip rules from appsettings.json
+ services.Configure(configuration.GetSection("IpRateLimitPolicies"));
+ // inject counter and rules stores
+ services.AddSingleton();
+ services.AddSingleton();
+ // Add framework services.
+ services.AddMvc();
+ services.AddSingleton();
+ // configuration (resolvers, counter key builders)
+ services.AddSingleton();
+ }
+ }
+}
diff --git a/InvestmentManager/InvestmentManager/appsettings.json b/InvestmentManager/InvestmentManager/appsettings.json
index c7069f1..bb435cd 100644
--- a/InvestmentManager/InvestmentManager/appsettings.json
+++ b/InvestmentManager/InvestmentManager/appsettings.json
@@ -32,5 +32,22 @@
],
"EvaluationTimeOnSeconds": 10,
"MinimumSecondsBetweenFailureNotifications": 60
+ },
+ "IpRateLimiting": {
+ "EnableEndpointRateLimiting": true,
+ "StackBlockedRequests": true,
+ "RealIpHeader": "X-Real-IP",
+ "ClientIdHeader": "X-ClientId",
+ "HttpStatusCode": 429,
+ "IpWhitelist": [ "23" ],
+ "EndpointWhitelist": [ "get:/api/license", "*:/api/status" ],
+ "ClientWhitelist": [ "test4", "test3" ],
+ "GeneralRules": [
+ {
+ "Endpoint": "*:/health/ready",
+ "Period": "10s",
+ "Limit": 1
+ }
+ ]
}
}