From 05aee20a9a2f95b607f4954f732f0643909fbed9 Mon Sep 17 00:00:00 2001 From: Yannis Standaert Date: Mon, 20 Jan 2025 09:52:15 +0100 Subject: [PATCH 01/36] added a release action --- .github/workflows/release.yml | 55 +++++++++++++++++++++++++++++++++++ build.cake | 1 - 2 files changed, 55 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/release.yml diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 00000000..b32fb1ab --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,55 @@ +name: Publish NuGet Packages + +on: + release: + types: [created] + +jobs: + publish: + runs-on: windows-2022 + timeout-minutes: 30 + + env: + DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true + DOTNET_CLI_TELEMETRY_OPTOUT: true + CAKE_NUGETAPIKEY: ${{ secrets.NUGETAPIKEY }} + + steps: + - uses: actions/checkout@v4 + + - uses: actions/cache@v3 + with: + path: | + ~/.nuget/packages + ~/.local/share/NuGet/v3-cache + key: ${{ runner.os }}-nuget-${{ hashFiles('**/*.csproj', '**/*.props', '**/*.targets') }} + restore-keys: | + ${{ runner.os }}-nuget- + + - name: Setup .NET + uses: actions/setup-dotnet@v3 + with: + dotnet-version: | + 4.6.1 + 4.7.2 + 4.8.2 + 6.0.x + 7.0.x + 8.0.x + + - name: Add msbuild to PATH + uses: microsoft/setup-msbuild@v2 + with: + vs-version: "[17.2,19.0)" + + - name: Install Cake Tool + run: dotnet tool install --global Cake.Tool + + - name: Run Cake Script to Build and Pack + run: dotnet cake build.cake --target=CreatePackages + + - name: Publish NuGet Packages + run: | + for %%f in (artifacts\*.nupkg) do ( + dotnet nuget push %%f --api-key ${{ secrets.NUGETAPIKEY }} --source https://api.nuget.org/v3/index.json + ) diff --git a/build.cake b/build.cake index 30676e98..a867f169 100644 --- a/build.cake +++ b/build.cake @@ -168,7 +168,6 @@ Task("Pack") if (configuration == "Release") { var projects = new[] { - "./Aikido.Zen.Core/Aikido.Zen.Core.csproj", "./Aikido.Zen.DotNetFramework/Aikido.Zen.DotNetFramework.csproj", "./Aikido.Zen.DotNetCore/Aikido.Zen.DotNetCore.csproj" }; From cb8839dd363340738403b313904bbfb2a6999a50 Mon Sep 17 00:00:00 2001 From: Yannis Standaert Date: Mon, 20 Jan 2025 10:06:54 +0100 Subject: [PATCH 02/36] beeter nuspec for dotnetframework --- .../Aikido.Zen.DotNetFramework.nuspec | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/Aikido.Zen.DotNetFramework/Aikido.Zen.DotNetFramework.nuspec b/Aikido.Zen.DotNetFramework/Aikido.Zen.DotNetFramework.nuspec index 1e6a9d8b..ea7b5e03 100644 --- a/Aikido.Zen.DotNetFramework/Aikido.Zen.DotNetFramework.nuspec +++ b/Aikido.Zen.DotNetFramework/Aikido.Zen.DotNetFramework.nuspec @@ -1,16 +1,14 @@ - $id$ - $version$ + Aikido.Zen.DotNetFramework + 0.0.1-alpha4 $title$ - $author$ + Aikido Security + Aikido Security + Aikido Security Zen .NET Framework Firewall false MIT - - http://project_url_here_or_delete_this_line/ - Aikido Zen, An in-app firewall for .NET - Summary of changes made in this release of the package. Copyright 2024 Aikido firewall .NET From 0a0f7d1ec7a44a30022b6b593bfa88079cb3b209 Mon Sep 17 00:00:00 2001 From: Yannis Standaert Date: Mon, 20 Jan 2025 10:20:17 +0100 Subject: [PATCH 03/36] updated nuspec files --- .../Aikido.Zen.DotNetCore.nuspec | 63 +++++++++++++++++++ .../Aikido.Zen.DotNetFramework.nuspec | 12 ++++ 2 files changed, 75 insertions(+) create mode 100644 Aikido.Zen.DotNetCore/Aikido.Zen.DotNetCore.nuspec diff --git a/Aikido.Zen.DotNetCore/Aikido.Zen.DotNetCore.nuspec b/Aikido.Zen.DotNetCore/Aikido.Zen.DotNetCore.nuspec new file mode 100644 index 00000000..c786d03a --- /dev/null +++ b/Aikido.Zen.DotNetCore/Aikido.Zen.DotNetCore.nuspec @@ -0,0 +1,63 @@ + + + + Aikido.Zen.DotNetCore + 0.0.1-alpha4 + $title$ + Aikido Security + Aikido Security + Aikido Security Zen .NET Core Firewall + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Aikido.Zen.DotNetFramework/Aikido.Zen.DotNetFramework.nuspec b/Aikido.Zen.DotNetFramework/Aikido.Zen.DotNetFramework.nuspec index ea7b5e03..aa5204d9 100644 --- a/Aikido.Zen.DotNetFramework/Aikido.Zen.DotNetFramework.nuspec +++ b/Aikido.Zen.DotNetFramework/Aikido.Zen.DotNetFramework.nuspec @@ -11,5 +11,17 @@ MIT Copyright 2024 Aikido firewall .NET + + + + + + + + + + + + \ No newline at end of file From c43ccc8a0a49fc43a0bfdfb24c9bea7928ab4ff9 Mon Sep 17 00:00:00 2001 From: Yannis Standaert Date: Thu, 16 Jan 2025 18:42:58 +0100 Subject: [PATCH 04/36] Update README.md to enhance installation instructions and supported frameworks for Zen Aikido --- README.md | 133 +++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 126 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index d8018bfd..6a270d56 100644 --- a/README.md +++ b/README.md @@ -18,11 +18,8 @@ Zen for .NET currently supports onwards of .NET xx. The latest tested version is Zen will autonomously protect your .NET applications from the inside against: -* 🛡️ [NoSQL injection attacks](https://www.aikido.dev/blog/web-application-security-vulnerabilities) * 🛡️ [SQL injection attacks](https://www.aikido.dev/blog/the-state-of-sql-injections) -* 🛡️ [Command injection attacks](https://www.aikido.dev/blog/command-injection-in-2024-unpacked) * 🛡️ [Path traversal attacks](https://owasp.org/www-community/attacks/Path_Traversal) -* 🛡️ [Server-side request forgery (SSRF)](./docs/ssrf.md) Zen operates autonomously on the same server as your .NET app to: @@ -31,15 +28,135 @@ Zen operates autonomously on the same server as your .NET app to: * ✅ Allow you to block specific users manually * ✅ Auto-generate API specifications ## Supported libraries and frameworks + ### Web frameworks -* ✅ TODO +* ✅ ASP.NET Core +* ✅ ASP.NET Framework ### Database drivers -* ✅ TODO +* ✅ Microsoft.Data.SqlClient +* ✅ System.Data.SqlClient +* ✅ Microsoft.Data.Sqlite +* ✅ MySql.Data.MySqlClient +* ✅ MySqlConnector +* ✅ Npgsql +* ✅ MySqlX ## Installation -TODO +### .NET Core + +- Install the package from NuGet: + +``` shell +dotnet add package Zen.Aikido +``` + +- Add the following to your `appsettings.json` file: (use secrets manager to store the API key) + +``` json +{ + "Aikido": { + "AikidoToken": "your-api-key" + } +} +``` + +- or add it as an environment variable + +``` shell +AIKIDO_TOKEN +``` + +If you are using a startup class, you can add the following to your `Startup.cs` file: + +``` csharp +public void ConfigureServices(IServiceCollection services) +{ + // other services + services.AddZenFirewall(Configuration); + // other services +} + +public void Configure(IApplicationBuilder app) +{ + // other middleware + app.UseZenFirewall(); // place this after userouting, or after authorization, but high enough in the pipeline to catch all requests + // other middleware +} +``` + +You can also set the user in your custom middleware, if you would like to block users by their identity. + +``` csharp +// add routing + .UseRouting() + // authorize users + .Use((context, next) => + { + var id = context.User?.Identity?.Name ?? "test"; + var name = context.User?.Identity?.Name ?? "Anonymous"; + if (!string.IsNullOrEmpty(id)) + Zen.SetUser(id, name, context); + return next(); + }) + // add Zen middleware + .UseZenFireWall() +``` + +### .NET Framework + +To add the Aikido token in the Web.config file, follow these steps: + +1. Open your `Web.config` file. +2. Locate the `` section. +3. Add the following key-value pair within the `` section: + +``` xml + +``` + +in your global.asax.cs file, add the following: + +``` csharp +protected void Application_Start() +{ + // other code + Zen.Start(); +} +``` + +if you are using OWIN, you can add the following to your `Startup.cs` file: + +``` csharp +public void Configuration(IAppBuilder app) +{ + // other code + Zen.Start(); +} +``` + +If you would like to block users by their identity, you can pass in a function to set the user, in your global.asax.cs file. + +``` csharp +public void Application_Start() +{ + // other code + Zen.SetUser(context => new User(context.User.Identity.Name, context.User.Identity.Name)); + Zen.Start(); +} +``` + +Or if you are using OWIN, you can add the following to your `Startup.cs` file: + +``` csharp +public void Configuration(IAppBuilder app) +{ + // other code + Zen.SetUser(context => new User(context.User.Identity.Name, context.User.Identity.Name)); + Zen.Start(); +} +``` ## Reporting to your Aikido Security dashboard @@ -89,7 +206,9 @@ address: support@aikido.dev or create an account at https://app.aikido.dev. ## Performance -TODO +| Without Zen | With Zen | Difference in ms | +|------------------|---------------|------------------| +| 3.64ms | 4.05ms | +0.41ms | ## Code of Conduct From c5486e23081d2dea2ffec5eed148e01dabeee557 Mon Sep 17 00:00:00 2001 From: Yannis Standaert Date: Thu, 16 Jan 2025 18:46:50 +0100 Subject: [PATCH 05/36] Updated feature list --- README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 6a270d56..52d6adef 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,11 @@ Zen operates autonomously on the same server as your .NET app to: * ✅ Secure your app like a classic web application firewall (WAF), but with none of the infrastructure or cost. * ✅ Rate limit specific API endpoints by IP or by user * ✅ Allow you to block specific users manually -* ✅ Auto-generate API specifications +* ✅ Allow you to block traffic by country +* ✅ Allow you to block traffic by bots +* ✅ Allow you to allow traffic by ip per endpoint + + ## Supported libraries and frameworks ### Web frameworks From 4538f66deb9eff36d5277b8818846605850306bf Mon Sep 17 00:00:00 2001 From: Yannis Standaert Date: Thu, 16 Jan 2025 18:49:29 +0100 Subject: [PATCH 06/36] added supported versions --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 52d6adef..7f54e582 100644 --- a/README.md +++ b/README.md @@ -34,8 +34,8 @@ Zen operates autonomously on the same server as your .NET app to: ## Supported libraries and frameworks ### Web frameworks -* ✅ ASP.NET Core -* ✅ ASP.NET Framework +* ✅ ASP.NET Core <= 8.0 +* ✅ ASP.NET Framework >= 4.6 and <= 4.8 ### Database drivers * ✅ Microsoft.Data.SqlClient From 402fcf54910905e1d0024faeaec7493b10ae91fb Mon Sep 17 00:00:00 2001 From: Yannis Standaert Date: Thu, 16 Jan 2025 19:06:19 +0100 Subject: [PATCH 07/36] removed benchmark + updated the framework list --- README.md | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 7f54e582..7a6d1000 100644 --- a/README.md +++ b/README.md @@ -34,8 +34,12 @@ Zen operates autonomously on the same server as your .NET app to: ## Supported libraries and frameworks ### Web frameworks -* ✅ ASP.NET Core <= 8.0 -* ✅ ASP.NET Framework >= 4.6 and <= 4.8 +* ✅ ASP.NET Core 6.0 +* ✅ ASP.NET Core 7.0 +* ✅ ASP.NET Core 8.0 +* ✅ ASP.NET Framework 4.6.x +* ✅ ASP.NET Framework 4.7.x +* ✅ ASP.NET Framework 4.8.x ### Database drivers * ✅ Microsoft.Data.SqlClient @@ -210,9 +214,7 @@ address: support@aikido.dev or create an account at https://app.aikido.dev. ## Performance -| Without Zen | With Zen | Difference in ms | -|------------------|---------------|------------------| -| 3.64ms | 4.05ms | +0.41ms | +TODO ## Code of Conduct From 50a70f76fa0df624ea0a25be62985b9c28a23a93 Mon Sep 17 00:00:00 2001 From: Yannis Standaert Date: Thu, 16 Jan 2025 19:09:34 +0100 Subject: [PATCH 08/36] added framework support in top description --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 7a6d1000..b6e73f6a 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ Zen is an embedded Web Application Firewall that autonomously protects your .NET Zen protects your .NET apps by preventing user input containing dangerous strings, which allow SQL injections. It runs on the same server as your .NET app for easy installation and zero maintenance. -Zen for .NET currently supports onwards of .NET xx. The latest tested version is .NET xx. +Zen for .NET currently supports onwards of .NET 4.6. The latest tested version is .NET 8.0. ## Features From cb87a264556eb5559760c55c5e926dc537dc4466 Mon Sep 17 00:00:00 2001 From: Yannis Standaert Date: Fri, 17 Jan 2025 10:34:14 +0100 Subject: [PATCH 09/36] small perf improvements for better benchmark results --- Aikido.Zen.Core/Helpers/AgentInfoHelper.cs | 49 ++++++++++--------- .../Middleware/ContextMiddleware.cs | 30 ++++++------ 2 files changed, 41 insertions(+), 38 deletions(-) diff --git a/Aikido.Zen.Core/Helpers/AgentInfoHelper.cs b/Aikido.Zen.Core/Helpers/AgentInfoHelper.cs index cccf51d2..dca64d5e 100644 --- a/Aikido.Zen.Core/Helpers/AgentInfoHelper.cs +++ b/Aikido.Zen.Core/Helpers/AgentInfoHelper.cs @@ -9,34 +9,37 @@ namespace Aikido.Zen.Core.Helpers /// internal class AgentInfoHelper { + // Cache the AgentInfo object to avoid repeated creation + private static readonly AgentInfo _cachedAgentInfo = new AgentInfo + { + Hostname = Environment.MachineName, + Os = new Os + { + Version = Environment.OSVersion.VersionString, + Name = Environment.OSVersion.Platform.ToString() + }, + Platform = new Platform + { + Version = Environment.Version.ToString(), + Arch = Environment.Version.Major >= 5 ? "core" : "framework" + }, + IpAddress = IPHelper.Server, + Library = "firewall-dotnet", + Version = "1.0.0", + // Determine if running in a serverless environment + Serverless = Environment.GetEnvironmentVariable("AWS_LAMBDA_FUNCTION_NAME") != null || Environment.GetEnvironmentVariable("WEBSITE_INSTANCE_ID") != null + }; + /// /// Gets information about the current runtime environment including OS, platform, and configuration details. /// /// An AgentInfo object containing the environment information. public static AgentInfo GetInfo() { - return new AgentInfo - { - Hostname = Environment.MachineName, - Os = new Os - { - Version = Environment.OSVersion.VersionString, - Name = Environment.OSVersion.Platform.ToString() - }, - Platform = new Platform - { - // version - Version = Environment.Version.ToString(), - // core or framework - Arch = Environment.Version.Major >= 5 ? "core" : "framework" - }, - IpAddress = IPHelper.Server, - DryMode = EnvironmentHelper.DryMode, - // check if lambda or azure function - Serverless = Environment.GetEnvironmentVariable("AWS_LAMBDA_FUNCTION_NAME") != null || Environment.GetEnvironmentVariable("WEBSITE_INSTANCE_ID") != null, - Library = "firewall-dotnet", - Version = "1.0.0" - }; + // Update only the fields that can change + _cachedAgentInfo.DryMode = EnvironmentHelper.DryMode; + + return _cachedAgentInfo; } - } + } } diff --git a/Aikido.Zen.DotNetCore/Middleware/ContextMiddleware.cs b/Aikido.Zen.DotNetCore/Middleware/ContextMiddleware.cs index 12cd697e..204b8836 100644 --- a/Aikido.Zen.DotNetCore/Middleware/ContextMiddleware.cs +++ b/Aikido.Zen.DotNetCore/Middleware/ContextMiddleware.cs @@ -18,48 +18,48 @@ public ContextMiddleware(IEnumerable endpointSources) public async Task InvokeAsync(HttpContext httpContext, RequestDelegate next) { - // this will be used to check for attacks + // Convert headers and query parameters to dictionaries once + var queryDictionary = httpContext.Request.Query.ToDictionary(q => q.Key, q => q.Value.ToArray()); + var headersDictionary = httpContext.Request.Headers.ToDictionary(h => h.Key, h => h.Value.ToArray()); + var context = new Context { Url = httpContext.Request.Path.ToString(), Method = httpContext.Request.Method, - Query = httpContext.Request.Query.ToDictionary(q => q.Key, q => q.Value.ToArray()), - Headers = httpContext.Request.Headers - .ToDictionary(h => h.Key, h => h.Value.ToArray()), - RemoteAddress = httpContext.Connection.RemoteIpAddress?.ToString() ?? string.Empty, + Query = queryDictionary, + Headers = headersDictionary, + RemoteAddress = httpContext.Connection.RemoteIpAddress?.ToString() ?? string.Empty, // no need to use X-FORWARDED-FOR, .NET Core already handles this Cookies = httpContext.Request.Cookies.ToDictionary(c => c.Key, c => c.Value), - UserAgent = httpContext.Request.Headers["User-Agent"].ToString(), + UserAgent = headersDictionary.TryGetValue("User-Agent", out var userAgent) ? userAgent.FirstOrDefault() : string.Empty, Source = Environment.Version.Major >= 5 ? "DotNetCore" : "DotNetFramework", Route = GetRoute(httpContext), }; - // no need to use X-FORWARDED-FOR, .NET Core already handles this - var clientIp = httpContext.Connection.RemoteIpAddress?.ToString(); + var clientIp = context.RemoteAddress; // Add request information to the agent, which will collect routes, users and stats // every x minutes, this information will be sent to the Zen server as a heartbeat event, and the collected info will be cleared - Agent.Instance.CaptureInboundRequest(context.User, httpContext.Request.Path, context.Method, clientIp); + Agent.Instance.CaptureInboundRequest(context.User, context.Url, context.Method, clientIp); try { var request = httpContext.Request; - // allow the body to be read multiple times request.EnableBuffering(); + var parsedUserInput = await HttpHelper.ReadAndFlattenHttpDataAsync( - queryParams: context.Query.ToDictionary(h => h.Key, h => string.Join(',', h.Value)), - headers: context.Headers.ToDictionary(h => h.Key, h => string.Join(',', h.Value)), + queryParams: queryDictionary.ToDictionary(h => h.Key, h => string.Join(',', h.Value)), + headers: headersDictionary.ToDictionary(h => h.Key, h => string.Join(',', h.Value)), cookies: context.Cookies, body: request.Body, contentType: request.ContentType, contentLength: request.ContentLength ?? 0 ); + context.ParsedUserInput = parsedUserInput; context.Body = request.Body; - } catch (Exception e) { - var message = e.Message; - var trace = e.StackTrace; + // Log the exception details if necessary throw; } From c6bd112632afa909f7cef3a4d67f967d53e43250 Mon Sep 17 00:00:00 2001 From: Yannis Standaert Date: Fri, 17 Jan 2025 10:50:55 +0100 Subject: [PATCH 10/36] add under construction for per for now --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b6e73f6a..ce946a68 100644 --- a/README.md +++ b/README.md @@ -214,7 +214,7 @@ address: support@aikido.dev or create an account at https://app.aikido.dev. ## Performance -TODO +![Under construction](https://img.icons8.com/emoji/20/000000/construction-emoji.png) Under construction ![Under construction](https://img.icons8.com/emoji/20/000000/construction-emoji.png) ## Code of Conduct From 7d2d27910ca590de363590778437da25a92315c0 Mon Sep 17 00:00:00 2001 From: Yannis Standaert Date: Mon, 20 Jan 2025 09:01:55 +0100 Subject: [PATCH 11/36] fix pr comment: arch means process architecture, not framework architecture --- Aikido.Zen.Core/Helpers/AgentInfoHelper.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Aikido.Zen.Core/Helpers/AgentInfoHelper.cs b/Aikido.Zen.Core/Helpers/AgentInfoHelper.cs index dca64d5e..f27b13ba 100644 --- a/Aikido.Zen.Core/Helpers/AgentInfoHelper.cs +++ b/Aikido.Zen.Core/Helpers/AgentInfoHelper.cs @@ -1,6 +1,7 @@ using Aikido.Zen.Core.Models; using System; using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; [assembly: InternalsVisibleTo("Aikido.Zen.Tests")] namespace Aikido.Zen.Core.Helpers { @@ -21,7 +22,7 @@ internal class AgentInfoHelper Platform = new Platform { Version = Environment.Version.ToString(), - Arch = Environment.Version.Major >= 5 ? "core" : "framework" + Arch = RuntimeInformation.ProcessArchitecture.ToString() }, IpAddress = IPHelper.Server, Library = "firewall-dotnet", From df1ec39b568c03d660ae63b8292144ccaff1294a Mon Sep 17 00:00:00 2001 From: Yannis Standaert Date: Mon, 20 Jan 2025 09:52:15 +0100 Subject: [PATCH 12/36] added a release action --- .github/workflows/release.yml | 55 +++++++++++++++++++++++++++++++++++ build.cake | 1 - 2 files changed, 55 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/release.yml diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 00000000..b32fb1ab --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,55 @@ +name: Publish NuGet Packages + +on: + release: + types: [created] + +jobs: + publish: + runs-on: windows-2022 + timeout-minutes: 30 + + env: + DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true + DOTNET_CLI_TELEMETRY_OPTOUT: true + CAKE_NUGETAPIKEY: ${{ secrets.NUGETAPIKEY }} + + steps: + - uses: actions/checkout@v4 + + - uses: actions/cache@v3 + with: + path: | + ~/.nuget/packages + ~/.local/share/NuGet/v3-cache + key: ${{ runner.os }}-nuget-${{ hashFiles('**/*.csproj', '**/*.props', '**/*.targets') }} + restore-keys: | + ${{ runner.os }}-nuget- + + - name: Setup .NET + uses: actions/setup-dotnet@v3 + with: + dotnet-version: | + 4.6.1 + 4.7.2 + 4.8.2 + 6.0.x + 7.0.x + 8.0.x + + - name: Add msbuild to PATH + uses: microsoft/setup-msbuild@v2 + with: + vs-version: "[17.2,19.0)" + + - name: Install Cake Tool + run: dotnet tool install --global Cake.Tool + + - name: Run Cake Script to Build and Pack + run: dotnet cake build.cake --target=CreatePackages + + - name: Publish NuGet Packages + run: | + for %%f in (artifacts\*.nupkg) do ( + dotnet nuget push %%f --api-key ${{ secrets.NUGETAPIKEY }} --source https://api.nuget.org/v3/index.json + ) diff --git a/build.cake b/build.cake index 30676e98..a867f169 100644 --- a/build.cake +++ b/build.cake @@ -168,7 +168,6 @@ Task("Pack") if (configuration == "Release") { var projects = new[] { - "./Aikido.Zen.Core/Aikido.Zen.Core.csproj", "./Aikido.Zen.DotNetFramework/Aikido.Zen.DotNetFramework.csproj", "./Aikido.Zen.DotNetCore/Aikido.Zen.DotNetCore.csproj" }; From 14dd65f96eafda9ff67373f4d193d784067126c4 Mon Sep 17 00:00:00 2001 From: Yannis Standaert Date: Mon, 20 Jan 2025 10:06:54 +0100 Subject: [PATCH 13/36] beeter nuspec for dotnetframework --- .../Aikido.Zen.DotNetFramework.nuspec | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/Aikido.Zen.DotNetFramework/Aikido.Zen.DotNetFramework.nuspec b/Aikido.Zen.DotNetFramework/Aikido.Zen.DotNetFramework.nuspec index 1e6a9d8b..ea7b5e03 100644 --- a/Aikido.Zen.DotNetFramework/Aikido.Zen.DotNetFramework.nuspec +++ b/Aikido.Zen.DotNetFramework/Aikido.Zen.DotNetFramework.nuspec @@ -1,16 +1,14 @@ - $id$ - $version$ + Aikido.Zen.DotNetFramework + 0.0.1-alpha4 $title$ - $author$ + Aikido Security + Aikido Security + Aikido Security Zen .NET Framework Firewall false MIT - - http://project_url_here_or_delete_this_line/ - Aikido Zen, An in-app firewall for .NET - Summary of changes made in this release of the package. Copyright 2024 Aikido firewall .NET From 79a5c464e3f75d4166fbfe66b0e8ade5b41e2a97 Mon Sep 17 00:00:00 2001 From: Yannis Standaert Date: Mon, 20 Jan 2025 10:20:17 +0100 Subject: [PATCH 14/36] updated nuspec files --- .../Aikido.Zen.DotNetCore.nuspec | 63 +++++++++++++++++++ .../Aikido.Zen.DotNetFramework.nuspec | 12 ++++ 2 files changed, 75 insertions(+) create mode 100644 Aikido.Zen.DotNetCore/Aikido.Zen.DotNetCore.nuspec diff --git a/Aikido.Zen.DotNetCore/Aikido.Zen.DotNetCore.nuspec b/Aikido.Zen.DotNetCore/Aikido.Zen.DotNetCore.nuspec new file mode 100644 index 00000000..c786d03a --- /dev/null +++ b/Aikido.Zen.DotNetCore/Aikido.Zen.DotNetCore.nuspec @@ -0,0 +1,63 @@ + + + + Aikido.Zen.DotNetCore + 0.0.1-alpha4 + $title$ + Aikido Security + Aikido Security + Aikido Security Zen .NET Core Firewall + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Aikido.Zen.DotNetFramework/Aikido.Zen.DotNetFramework.nuspec b/Aikido.Zen.DotNetFramework/Aikido.Zen.DotNetFramework.nuspec index ea7b5e03..aa5204d9 100644 --- a/Aikido.Zen.DotNetFramework/Aikido.Zen.DotNetFramework.nuspec +++ b/Aikido.Zen.DotNetFramework/Aikido.Zen.DotNetFramework.nuspec @@ -11,5 +11,17 @@ MIT Copyright 2024 Aikido firewall .NET + + + + + + + + + + + + \ No newline at end of file From 71503b7a4e08e55d2eb82899a712531482382cef Mon Sep 17 00:00:00 2001 From: Yannis Standaert Date: Mon, 20 Jan 2025 16:56:05 +0100 Subject: [PATCH 15/36] NPoco sql detection support --- Aikido.Zen.Core/Aikido.Zen.Core.csproj | 2 +- Aikido.Zen.Core/Helpers/ReflectionHelper.cs | 11 +++++----- Aikido.Zen.Core/Models/AgentContext.cs | 2 ++ Aikido.Zen.Core/Patches/SqlClientPatcher.cs | 4 +++- .../Aikido.Zen.DotNetCore.nuspec | 4 +++- .../Patches/SqlClientPatches.cs | 8 ++++++- .../Aikido.Zen.DotNetFramework.nuspec | 18 +++++++++------- .../Aikido.Zen.DotNetFramework.targets | 21 +++++++++++++++++++ .../Patches/SqlClientPatches.cs | 18 +++++++++++++++- 9 files changed, 70 insertions(+), 18 deletions(-) create mode 100644 Aikido.Zen.DotNetFramework/Aikido.Zen.DotNetFramework.targets diff --git a/Aikido.Zen.Core/Aikido.Zen.Core.csproj b/Aikido.Zen.Core/Aikido.Zen.Core.csproj index 9cf940ba..cbacc671 100644 --- a/Aikido.Zen.Core/Aikido.Zen.Core.csproj +++ b/Aikido.Zen.Core/Aikido.Zen.Core.csproj @@ -39,6 +39,6 @@ - + diff --git a/Aikido.Zen.Core/Helpers/ReflectionHelper.cs b/Aikido.Zen.Core/Helpers/ReflectionHelper.cs index 818eb324..d3eab65d 100644 --- a/Aikido.Zen.Core/Helpers/ReflectionHelper.cs +++ b/Aikido.Zen.Core/Helpers/ReflectionHelper.cs @@ -32,11 +32,9 @@ static ReflectionHelper() public static MethodInfo GetMethodFromAssembly(string assemblyName, string typeName, string methodName, params string[] parameterTypeNames) { // Attempt to load the assembly - // Attempt to get the assembly from the cache, if not found, load it if (!_assemblies.TryGetValue(assemblyName, out var assembly)) { assembly = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault(a => a.GetName().Name == assemblyName); - // If the assembly is not loaded, and the assembly path exists, load it if (File.Exists($"{assemblyName}.dll") && assembly == null) { assembly = Assembly.LoadFrom($"{assemblyName}.dll"); @@ -49,13 +47,16 @@ public static MethodInfo GetMethodFromAssembly(string assemblyName, string typeN var typeKey = $"{assemblyName}.{typeName}"; if (!_types.TryGetValue(typeKey, out var type)) { - type = assembly.ExportedTypes.FirstOrDefault(t => t.Name == typeName); + type = assembly.GetType(typeKey); // Ensure full type name is used if (type == null) return null; _types[typeKey] = type; } - // Use reflection to get the method - var method = type.GetMethods().FirstOrDefault(m => m.Name == methodName && m.GetParameters().All(p => parameterTypeNames.Any(ptn => ptn == p.ParameterType.FullName))); + // Use reflection to get the method, make sure to check for public, internal and private methods + var method = type + .GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static) + .FirstOrDefault(m => m.Name == methodName && + m.GetParameters().Select(p => p.ParameterType.FullName).SequenceEqual(parameterTypeNames)); return method; } diff --git a/Aikido.Zen.Core/Models/AgentContext.cs b/Aikido.Zen.Core/Models/AgentContext.cs index 231615da..017374f1 100644 --- a/Aikido.Zen.Core/Models/AgentContext.cs +++ b/Aikido.Zen.Core/Models/AgentContext.cs @@ -27,6 +27,8 @@ public class AgentContext private long _started = DateTimeHelper.UTCNowUnixMilliseconds(); public long ConfigLastUpdated { get; set; } = 0; + public IList Patches { get; set; } = new List(); + public void AddRequest() { diff --git a/Aikido.Zen.Core/Patches/SqlClientPatcher.cs b/Aikido.Zen.Core/Patches/SqlClientPatcher.cs index 690238f4..fd6299a3 100644 --- a/Aikido.Zen.Core/Patches/SqlClientPatcher.cs +++ b/Aikido.Zen.Core/Patches/SqlClientPatcher.cs @@ -10,7 +10,8 @@ public static class SqlClientPatcher { public static bool OnCommandExecuting(object[] __args, MethodBase __originalMethod, DbCommand __instance, string assembly, Context context) { - var command = __instance; + var command = __instance + ?? __args[0] as DbCommand; var methodInfo = __originalMethod as MethodInfo; if (context == null) @@ -37,6 +38,7 @@ public static SQLDialect GetDialect(string assembly) { case "System.Data.SqlClient": case "Microsoft.Data.SqlClient": + case "System.Data.SqlServerCe": return SQLDialect.MicrosoftSQL; case "MySql.Data": case "MySqlConnector": diff --git a/Aikido.Zen.DotNetCore/Aikido.Zen.DotNetCore.nuspec b/Aikido.Zen.DotNetCore/Aikido.Zen.DotNetCore.nuspec index c786d03a..4d37aba7 100644 --- a/Aikido.Zen.DotNetCore/Aikido.Zen.DotNetCore.nuspec +++ b/Aikido.Zen.DotNetCore/Aikido.Zen.DotNetCore.nuspec @@ -58,6 +58,8 @@ - + + + \ No newline at end of file diff --git a/Aikido.Zen.DotNetCore/Patches/SqlClientPatches.cs b/Aikido.Zen.DotNetCore/Patches/SqlClientPatches.cs index 81e86345..a4e2f0db 100644 --- a/Aikido.Zen.DotNetCore/Patches/SqlClientPatches.cs +++ b/Aikido.Zen.DotNetCore/Patches/SqlClientPatches.cs @@ -46,6 +46,11 @@ public static void ApplyPatches(Harmony harmony) PatchMethod(harmony, "MySqlX", "XDevAPI.Relational.Table", "Insert"); PatchMethod(harmony, "MySqlX", "XDevAPI.Relational.Table", "Update"); PatchMethod(harmony, "MySqlX", "XDevAPI.Relational.Table", "Delete"); + + // NPoco + PatchMethod(harmony, "NPoco", "Database", "ExecuteReaderHelper", "System.Data.Common.DbCommand"); + PatchMethod(harmony, "NPoco", "Database", "ExecuteNonQueryHelper", "System.Data.Common.DbCommand"); + PatchMethod(harmony, "NPoco", "Database", "ExecuteScalarHelper", "System.Data.Common.DbCommand"); } private static void PatchMethod(Harmony harmony, string assemblyName, string typeName, string methodName, params string[] parameterTypeNames) @@ -59,7 +64,8 @@ private static void PatchMethod(Harmony harmony, string assemblyName, string typ private static bool OnCommandExecuting(object[] __args, MethodBase __originalMethod, object __instance) { - var dbCommand = __instance as System.Data.Common.DbCommand; + var dbCommand = __instance as System.Data.Common.DbCommand + ?? __args[0] as System.Data.Common.DbCommand; if (dbCommand == null) return true; var assembly = __instance.GetType().Assembly.FullName?.Split(", Culture=")[0]; return Aikido.Zen.Core.Patches.SqlClientPatcher.OnCommandExecuting(__args, __originalMethod, dbCommand, assembly, Zen.GetContext()); diff --git a/Aikido.Zen.DotNetFramework/Aikido.Zen.DotNetFramework.nuspec b/Aikido.Zen.DotNetFramework/Aikido.Zen.DotNetFramework.nuspec index aa5204d9..d217ac70 100644 --- a/Aikido.Zen.DotNetFramework/Aikido.Zen.DotNetFramework.nuspec +++ b/Aikido.Zen.DotNetFramework/Aikido.Zen.DotNetFramework.nuspec @@ -11,17 +11,19 @@ MIT Copyright 2024 Aikido firewall .NET - - - - - - - + + + + + + + + + + - \ No newline at end of file diff --git a/Aikido.Zen.DotNetFramework/Aikido.Zen.DotNetFramework.targets b/Aikido.Zen.DotNetFramework/Aikido.Zen.DotNetFramework.targets new file mode 100644 index 00000000..b44589a7 --- /dev/null +++ b/Aikido.Zen.DotNetFramework/Aikido.Zen.DotNetFramework.targets @@ -0,0 +1,21 @@ + + + + + libraries\libzen_internals_x86_64-pc-windows-gnu.dll + PreserveNewest + + + libraries\libzen_internals_x86_64-pc-windows-gnu.dll.sha256sum + PreserveNewest + + + + + + + + + + + \ No newline at end of file diff --git a/Aikido.Zen.DotNetFramework/Patches/SqlClientPatches.cs b/Aikido.Zen.DotNetFramework/Patches/SqlClientPatches.cs index d9865ab5..b0576e27 100644 --- a/Aikido.Zen.DotNetFramework/Patches/SqlClientPatches.cs +++ b/Aikido.Zen.DotNetFramework/Patches/SqlClientPatches.cs @@ -3,6 +3,7 @@ using HarmonyLib; using Aikido.Zen.Core.Models; using Aikido.Zen.Core.Helpers; +using Aikido.Zen.Core; namespace Aikido.Zen.DotNetFramework.Patches { @@ -27,6 +28,14 @@ public static void ApplyPatches(Harmony harmony) PatchMethod(harmony, "System.Data.SqlClient", "SqlCommand", "ExecuteScalar"); PatchMethod(harmony, "System.Data.SqlClient", "SqlCommand", "ExecuteReader", "System.Data.CommandBehavior"); + //SQL ServerCE + PatchMethod(harmony, "System.Data.SqlServerCe", "SqlCeCommand", "ExecuteNonQuery"); + PatchMethod(harmony, "System.Data.SqlServerCe", "SqlCeCommand", "ExecuteScalar"); + PatchMethod(harmony, "System.Data.SqlServerCe", "SqlCeCommand", "ExecuteReader", "System.Data.CommandBehavior"); + PatchMethod(harmony, "System.Data.SqlServerCe", "SqlCeCommand", "ExecuteNonQuery"); + PatchMethod(harmony, "System.Data.SqlServerCe", "SqlCeCommand", "ExecuteScalar"); + PatchMethod(harmony, "System.Data.SqlServerCe", "SqlCeCommand", "ExecuteReader", "System.Data.CommandBehavior"); + // SQLite PatchMethod(harmony, "Microsoft.Data.Sqlite", "SqliteCommand", "ExecuteNonQuery"); PatchMethod(harmony, "Microsoft.Data.Sqlite", "SqliteCommand", "ExecuteScalar"); @@ -50,6 +59,11 @@ public static void ApplyPatches(Harmony harmony) PatchMethod(harmony, "MySqlX", "XDevAPI.Relational.Table", "Insert"); PatchMethod(harmony, "MySqlX", "XDevAPI.Relational.Table", "Update"); PatchMethod(harmony, "MySqlX", "XDevAPI.Relational.Table", "Delete"); + + // NPoco + PatchMethod(harmony, "NPoco", "Database", "ExecuteReaderHelper", "System.Data.Common.DbCommand"); + PatchMethod(harmony, "NPoco", "Database", "ExecuteNonQueryHelper", "System.Data.Common.DbCommand"); + PatchMethod(harmony, "NPoco", "Database", "ExecuteScalarHelper", "System.Data.Common.DbCommand"); } /// @@ -66,6 +80,7 @@ private static void PatchMethod(Harmony harmony, string assemblyName, string typ if (method != null) { harmony.Patch(method, new HarmonyMethod(typeof(SqlClientPatches).GetMethod(nameof(OnCommandExecuting), BindingFlags.Static | BindingFlags.NonPublic))); + Agent.Instance.Context.Patches.Add($"{assemblyName}.{typeName}.{methodName}"); } } @@ -78,7 +93,8 @@ private static void PatchMethod(Harmony harmony, string assemblyName, string typ /// True if the original method should continue execution; otherwise, false. private static bool OnCommandExecuting(object[] __args, MethodBase __originalMethod, object __instance) { - var dbCommand = __instance as System.Data.Common.DbCommand; + var dbCommand = __instance as System.Data.Common.DbCommand + ?? __args[0] as System.Data.Common.DbCommand; if (dbCommand == null) return true; var assembly = __instance.GetType().Assembly.FullName?.Split(new[] { ", Culture=" }, StringSplitOptions.RemoveEmptyEntries)[0]; return Aikido.Zen.Core.Patches.SqlClientPatcher.OnCommandExecuting(__args, __originalMethod, dbCommand, assembly, Zen.GetContext()); From 44a1444d37cac62ebb222848c1a5e3bb663daaa4 Mon Sep 17 00:00:00 2001 From: Yannis Standaert Date: Mon, 20 Jan 2025 17:41:29 +0100 Subject: [PATCH 16/36] fixing nuget packages --- .../Aikido.Zen.DotNetCore.nuspec | 21 +++++++++---------- .../Aikido.Zen.DotNetCore.targets | 16 ++++++++++++++ .../Middleware/ContextMiddleware.cs | 7 ++++--- 3 files changed, 30 insertions(+), 14 deletions(-) create mode 100644 Aikido.Zen.DotNetCore/Aikido.Zen.DotNetCore.targets diff --git a/Aikido.Zen.DotNetCore/Aikido.Zen.DotNetCore.nuspec b/Aikido.Zen.DotNetCore/Aikido.Zen.DotNetCore.nuspec index 4d37aba7..3c159260 100644 --- a/Aikido.Zen.DotNetCore/Aikido.Zen.DotNetCore.nuspec +++ b/Aikido.Zen.DotNetCore/Aikido.Zen.DotNetCore.nuspec @@ -2,7 +2,7 @@ Aikido.Zen.DotNetCore - 0.0.1-alpha4 + 0.0.1-alpha5 $title$ Aikido Security Aikido Security @@ -51,15 +51,14 @@ - - - - - - - - - - + + + + + + + + + \ No newline at end of file diff --git a/Aikido.Zen.DotNetCore/Aikido.Zen.DotNetCore.targets b/Aikido.Zen.DotNetCore/Aikido.Zen.DotNetCore.targets new file mode 100644 index 00000000..f84a993f --- /dev/null +++ b/Aikido.Zen.DotNetCore/Aikido.Zen.DotNetCore.targets @@ -0,0 +1,16 @@ + + + + + PreserveNewest + + + + + + + + + + + \ No newline at end of file diff --git a/Aikido.Zen.DotNetCore/Middleware/ContextMiddleware.cs b/Aikido.Zen.DotNetCore/Middleware/ContextMiddleware.cs index 204b8836..ababe9c9 100644 --- a/Aikido.Zen.DotNetCore/Middleware/ContextMiddleware.cs +++ b/Aikido.Zen.DotNetCore/Middleware/ContextMiddleware.cs @@ -2,6 +2,7 @@ using Aikido.Zen.Core.Helpers; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Routing; +using System.Collections.Concurrent; namespace Aikido.Zen.DotNetCore.Middleware { @@ -18,9 +19,9 @@ public ContextMiddleware(IEnumerable endpointSources) public async Task InvokeAsync(HttpContext httpContext, RequestDelegate next) { - // Convert headers and query parameters to dictionaries once - var queryDictionary = httpContext.Request.Query.ToDictionary(q => q.Key, q => q.Value.ToArray()); - var headersDictionary = httpContext.Request.Headers.ToDictionary(h => h.Key, h => h.Value.ToArray()); + // Convert headers and query parameters to thread-safe dictionaries + var queryDictionary = new ConcurrentDictionary(httpContext.Request.Query.ToDictionary(q => q.Key, q => q.Value.ToArray())); + var headersDictionary = new ConcurrentDictionary(httpContext.Request.Headers.ToDictionary(h => h.Key, h => h.Value.ToArray())); var context = new Context { From daf3adec2ff79a7f52c30023352acabe5c55a324 Mon Sep 17 00:00:00 2001 From: Yannis Standaert Date: Tue, 21 Jan 2025 09:05:02 +0100 Subject: [PATCH 17/36] fix tests --- Aikido.Zen.Core/Helpers/AgentInfoHelper.cs | 3 ++- Aikido.Zen.Test/AgentInfoHelperTests.cs | 5 +++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/Aikido.Zen.Core/Helpers/AgentInfoHelper.cs b/Aikido.Zen.Core/Helpers/AgentInfoHelper.cs index f27b13ba..cab6bb9a 100644 --- a/Aikido.Zen.Core/Helpers/AgentInfoHelper.cs +++ b/Aikido.Zen.Core/Helpers/AgentInfoHelper.cs @@ -39,8 +39,9 @@ public static AgentInfo GetInfo() { // Update only the fields that can change _cachedAgentInfo.DryMode = EnvironmentHelper.DryMode; + _cachedAgentInfo.Serverless = Environment.GetEnvironmentVariable("AWS_LAMBDA_FUNCTION_NAME") != null || Environment.GetEnvironmentVariable("WEBSITE_INSTANCE_ID") != null; - return _cachedAgentInfo; + return _cachedAgentInfo; } } } diff --git a/Aikido.Zen.Test/AgentInfoHelperTests.cs b/Aikido.Zen.Test/AgentInfoHelperTests.cs index 7c4a9f93..05215909 100644 --- a/Aikido.Zen.Test/AgentInfoHelperTests.cs +++ b/Aikido.Zen.Test/AgentInfoHelperTests.cs @@ -1,3 +1,4 @@ +using System.Runtime.InteropServices; using Aikido.Zen.Core.Helpers; namespace Aikido.Zen.Test @@ -47,7 +48,7 @@ public void GetInfo_ShouldReturnValidAgentInfo() // Platform Info Assert.That(agentInfo.Platform.Version, Is.EqualTo(Environment.Version.ToString())); - Assert.That(agentInfo.Platform.Arch, Is.EqualTo(Environment.Version.Major >= 5 ? "core" : "framework")); + Assert.That(agentInfo.Platform.Arch, Is.EqualTo(RuntimeInformation.ProcessArchitecture.ToString())); }); } @@ -101,7 +102,7 @@ public void GetInfo_PlatformArchitecture_Core() var agentInfo = AgentInfoHelper.GetInfo(); // Assert - Assert.That(agentInfo.Platform.Arch, Is.EqualTo("core")); + Assert.That(agentInfo.Platform.Arch, Is.EqualTo(RuntimeInformation.ProcessArchitecture.ToString())); } } From 7e36549362cbc32ea81bf6e4849ce3ad2c555c93 Mon Sep 17 00:00:00 2001 From: Yannis Standaert Date: Mon, 20 Jan 2025 09:52:15 +0100 Subject: [PATCH 18/36] added a release action --- .github/workflows/release.yml | 55 +++++++++++++++++++++++++++++++++++ build.cake | 1 - 2 files changed, 55 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/release.yml diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 00000000..b32fb1ab --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,55 @@ +name: Publish NuGet Packages + +on: + release: + types: [created] + +jobs: + publish: + runs-on: windows-2022 + timeout-minutes: 30 + + env: + DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true + DOTNET_CLI_TELEMETRY_OPTOUT: true + CAKE_NUGETAPIKEY: ${{ secrets.NUGETAPIKEY }} + + steps: + - uses: actions/checkout@v4 + + - uses: actions/cache@v3 + with: + path: | + ~/.nuget/packages + ~/.local/share/NuGet/v3-cache + key: ${{ runner.os }}-nuget-${{ hashFiles('**/*.csproj', '**/*.props', '**/*.targets') }} + restore-keys: | + ${{ runner.os }}-nuget- + + - name: Setup .NET + uses: actions/setup-dotnet@v3 + with: + dotnet-version: | + 4.6.1 + 4.7.2 + 4.8.2 + 6.0.x + 7.0.x + 8.0.x + + - name: Add msbuild to PATH + uses: microsoft/setup-msbuild@v2 + with: + vs-version: "[17.2,19.0)" + + - name: Install Cake Tool + run: dotnet tool install --global Cake.Tool + + - name: Run Cake Script to Build and Pack + run: dotnet cake build.cake --target=CreatePackages + + - name: Publish NuGet Packages + run: | + for %%f in (artifacts\*.nupkg) do ( + dotnet nuget push %%f --api-key ${{ secrets.NUGETAPIKEY }} --source https://api.nuget.org/v3/index.json + ) diff --git a/build.cake b/build.cake index 30676e98..a867f169 100644 --- a/build.cake +++ b/build.cake @@ -168,7 +168,6 @@ Task("Pack") if (configuration == "Release") { var projects = new[] { - "./Aikido.Zen.Core/Aikido.Zen.Core.csproj", "./Aikido.Zen.DotNetFramework/Aikido.Zen.DotNetFramework.csproj", "./Aikido.Zen.DotNetCore/Aikido.Zen.DotNetCore.csproj" }; From 92b7f3cdfae95db65c79c612afb08caa7de2509a Mon Sep 17 00:00:00 2001 From: Yannis Standaert Date: Mon, 20 Jan 2025 10:06:54 +0100 Subject: [PATCH 19/36] beeter nuspec for dotnetframework --- .../Aikido.Zen.DotNetFramework.nuspec | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/Aikido.Zen.DotNetFramework/Aikido.Zen.DotNetFramework.nuspec b/Aikido.Zen.DotNetFramework/Aikido.Zen.DotNetFramework.nuspec index 1e6a9d8b..ea7b5e03 100644 --- a/Aikido.Zen.DotNetFramework/Aikido.Zen.DotNetFramework.nuspec +++ b/Aikido.Zen.DotNetFramework/Aikido.Zen.DotNetFramework.nuspec @@ -1,16 +1,14 @@ - $id$ - $version$ + Aikido.Zen.DotNetFramework + 0.0.1-alpha4 $title$ - $author$ + Aikido Security + Aikido Security + Aikido Security Zen .NET Framework Firewall false MIT - - http://project_url_here_or_delete_this_line/ - Aikido Zen, An in-app firewall for .NET - Summary of changes made in this release of the package. Copyright 2024 Aikido firewall .NET From 21f8427fe46841b9c30bc33355aadbb9100fc1ef Mon Sep 17 00:00:00 2001 From: Yannis Standaert Date: Mon, 20 Jan 2025 10:20:17 +0100 Subject: [PATCH 20/36] updated nuspec files --- .../Aikido.Zen.DotNetCore.nuspec | 63 +++++++++++++++++++ .../Aikido.Zen.DotNetFramework.nuspec | 12 ++++ 2 files changed, 75 insertions(+) create mode 100644 Aikido.Zen.DotNetCore/Aikido.Zen.DotNetCore.nuspec diff --git a/Aikido.Zen.DotNetCore/Aikido.Zen.DotNetCore.nuspec b/Aikido.Zen.DotNetCore/Aikido.Zen.DotNetCore.nuspec new file mode 100644 index 00000000..c786d03a --- /dev/null +++ b/Aikido.Zen.DotNetCore/Aikido.Zen.DotNetCore.nuspec @@ -0,0 +1,63 @@ + + + + Aikido.Zen.DotNetCore + 0.0.1-alpha4 + $title$ + Aikido Security + Aikido Security + Aikido Security Zen .NET Core Firewall + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Aikido.Zen.DotNetFramework/Aikido.Zen.DotNetFramework.nuspec b/Aikido.Zen.DotNetFramework/Aikido.Zen.DotNetFramework.nuspec index ea7b5e03..aa5204d9 100644 --- a/Aikido.Zen.DotNetFramework/Aikido.Zen.DotNetFramework.nuspec +++ b/Aikido.Zen.DotNetFramework/Aikido.Zen.DotNetFramework.nuspec @@ -11,5 +11,17 @@ MIT Copyright 2024 Aikido firewall .NET + + + + + + + + + + + + \ No newline at end of file From 95acf997abf4b7f625253e9103f24aabc1df189b Mon Sep 17 00:00:00 2001 From: Yannis Standaert Date: Mon, 20 Jan 2025 16:56:05 +0100 Subject: [PATCH 21/36] NPoco sql detection support --- Aikido.Zen.Core/Aikido.Zen.Core.csproj | 2 +- Aikido.Zen.Core/Helpers/ReflectionHelper.cs | 9 ++++---- Aikido.Zen.Core/Models/AgentContext.cs | 2 ++ Aikido.Zen.Core/Patches/SqlClientPatcher.cs | 4 +++- .../Aikido.Zen.DotNetCore.nuspec | 4 +++- .../Patches/SqlClientPatches.cs | 8 ++++++- .../Aikido.Zen.DotNetFramework.nuspec | 18 +++++++++------- .../Aikido.Zen.DotNetFramework.targets | 21 +++++++++++++++++++ .../Patches/SqlClientPatches.cs | 18 +++++++++++++++- 9 files changed, 69 insertions(+), 17 deletions(-) create mode 100644 Aikido.Zen.DotNetFramework/Aikido.Zen.DotNetFramework.targets diff --git a/Aikido.Zen.Core/Aikido.Zen.Core.csproj b/Aikido.Zen.Core/Aikido.Zen.Core.csproj index 9cf940ba..cbacc671 100644 --- a/Aikido.Zen.Core/Aikido.Zen.Core.csproj +++ b/Aikido.Zen.Core/Aikido.Zen.Core.csproj @@ -39,6 +39,6 @@ - + diff --git a/Aikido.Zen.Core/Helpers/ReflectionHelper.cs b/Aikido.Zen.Core/Helpers/ReflectionHelper.cs index 763f1a80..4953d89b 100644 --- a/Aikido.Zen.Core/Helpers/ReflectionHelper.cs +++ b/Aikido.Zen.Core/Helpers/ReflectionHelper.cs @@ -32,11 +32,9 @@ static ReflectionHelper() public static MethodInfo GetMethodFromAssembly(string assemblyName, string typeName, string methodName, params string[] parameterTypeNames) { // Attempt to load the assembly - // Attempt to get the assembly from the cache, if not found, load it if (!_assemblies.TryGetValue(assemblyName, out var assembly)) { assembly = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault(a => a.GetName().Name == assemblyName); - // If the assembly is not loaded, and the assembly path exists, load it if (File.Exists($"{assemblyName}.dll") && assembly == null) { assembly = Assembly.LoadFrom($"{assemblyName}.dll"); @@ -54,8 +52,11 @@ public static MethodInfo GetMethodFromAssembly(string assemblyName, string typeN _types[typeKey] = type; } - // Use reflection to get the method - var method = type.GetMethods().FirstOrDefault(m => m.Name == methodName && m.GetParameters().All(p => parameterTypeNames.Any(ptn => ptn == p.ParameterType.FullName))); + // Use reflection to get the method, make sure to check for public, internal and private methods + var method = type + .GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static) + .FirstOrDefault(m => m.Name == methodName && + m.GetParameters().Select(p => p.ParameterType.FullName).SequenceEqual(parameterTypeNames)); return method; } diff --git a/Aikido.Zen.Core/Models/AgentContext.cs b/Aikido.Zen.Core/Models/AgentContext.cs index 231615da..017374f1 100644 --- a/Aikido.Zen.Core/Models/AgentContext.cs +++ b/Aikido.Zen.Core/Models/AgentContext.cs @@ -27,6 +27,8 @@ public class AgentContext private long _started = DateTimeHelper.UTCNowUnixMilliseconds(); public long ConfigLastUpdated { get; set; } = 0; + public IList Patches { get; set; } = new List(); + public void AddRequest() { diff --git a/Aikido.Zen.Core/Patches/SqlClientPatcher.cs b/Aikido.Zen.Core/Patches/SqlClientPatcher.cs index 690238f4..fd6299a3 100644 --- a/Aikido.Zen.Core/Patches/SqlClientPatcher.cs +++ b/Aikido.Zen.Core/Patches/SqlClientPatcher.cs @@ -10,7 +10,8 @@ public static class SqlClientPatcher { public static bool OnCommandExecuting(object[] __args, MethodBase __originalMethod, DbCommand __instance, string assembly, Context context) { - var command = __instance; + var command = __instance + ?? __args[0] as DbCommand; var methodInfo = __originalMethod as MethodInfo; if (context == null) @@ -37,6 +38,7 @@ public static SQLDialect GetDialect(string assembly) { case "System.Data.SqlClient": case "Microsoft.Data.SqlClient": + case "System.Data.SqlServerCe": return SQLDialect.MicrosoftSQL; case "MySql.Data": case "MySqlConnector": diff --git a/Aikido.Zen.DotNetCore/Aikido.Zen.DotNetCore.nuspec b/Aikido.Zen.DotNetCore/Aikido.Zen.DotNetCore.nuspec index c786d03a..4d37aba7 100644 --- a/Aikido.Zen.DotNetCore/Aikido.Zen.DotNetCore.nuspec +++ b/Aikido.Zen.DotNetCore/Aikido.Zen.DotNetCore.nuspec @@ -58,6 +58,8 @@ - + + + \ No newline at end of file diff --git a/Aikido.Zen.DotNetCore/Patches/SqlClientPatches.cs b/Aikido.Zen.DotNetCore/Patches/SqlClientPatches.cs index 81e86345..a4e2f0db 100644 --- a/Aikido.Zen.DotNetCore/Patches/SqlClientPatches.cs +++ b/Aikido.Zen.DotNetCore/Patches/SqlClientPatches.cs @@ -46,6 +46,11 @@ public static void ApplyPatches(Harmony harmony) PatchMethod(harmony, "MySqlX", "XDevAPI.Relational.Table", "Insert"); PatchMethod(harmony, "MySqlX", "XDevAPI.Relational.Table", "Update"); PatchMethod(harmony, "MySqlX", "XDevAPI.Relational.Table", "Delete"); + + // NPoco + PatchMethod(harmony, "NPoco", "Database", "ExecuteReaderHelper", "System.Data.Common.DbCommand"); + PatchMethod(harmony, "NPoco", "Database", "ExecuteNonQueryHelper", "System.Data.Common.DbCommand"); + PatchMethod(harmony, "NPoco", "Database", "ExecuteScalarHelper", "System.Data.Common.DbCommand"); } private static void PatchMethod(Harmony harmony, string assemblyName, string typeName, string methodName, params string[] parameterTypeNames) @@ -59,7 +64,8 @@ private static void PatchMethod(Harmony harmony, string assemblyName, string typ private static bool OnCommandExecuting(object[] __args, MethodBase __originalMethod, object __instance) { - var dbCommand = __instance as System.Data.Common.DbCommand; + var dbCommand = __instance as System.Data.Common.DbCommand + ?? __args[0] as System.Data.Common.DbCommand; if (dbCommand == null) return true; var assembly = __instance.GetType().Assembly.FullName?.Split(", Culture=")[0]; return Aikido.Zen.Core.Patches.SqlClientPatcher.OnCommandExecuting(__args, __originalMethod, dbCommand, assembly, Zen.GetContext()); diff --git a/Aikido.Zen.DotNetFramework/Aikido.Zen.DotNetFramework.nuspec b/Aikido.Zen.DotNetFramework/Aikido.Zen.DotNetFramework.nuspec index aa5204d9..d217ac70 100644 --- a/Aikido.Zen.DotNetFramework/Aikido.Zen.DotNetFramework.nuspec +++ b/Aikido.Zen.DotNetFramework/Aikido.Zen.DotNetFramework.nuspec @@ -11,17 +11,19 @@ MIT Copyright 2024 Aikido firewall .NET - - - - - - - + + + + + + + + + + - \ No newline at end of file diff --git a/Aikido.Zen.DotNetFramework/Aikido.Zen.DotNetFramework.targets b/Aikido.Zen.DotNetFramework/Aikido.Zen.DotNetFramework.targets new file mode 100644 index 00000000..b44589a7 --- /dev/null +++ b/Aikido.Zen.DotNetFramework/Aikido.Zen.DotNetFramework.targets @@ -0,0 +1,21 @@ + + + + + libraries\libzen_internals_x86_64-pc-windows-gnu.dll + PreserveNewest + + + libraries\libzen_internals_x86_64-pc-windows-gnu.dll.sha256sum + PreserveNewest + + + + + + + + + + + \ No newline at end of file diff --git a/Aikido.Zen.DotNetFramework/Patches/SqlClientPatches.cs b/Aikido.Zen.DotNetFramework/Patches/SqlClientPatches.cs index d9865ab5..b0576e27 100644 --- a/Aikido.Zen.DotNetFramework/Patches/SqlClientPatches.cs +++ b/Aikido.Zen.DotNetFramework/Patches/SqlClientPatches.cs @@ -3,6 +3,7 @@ using HarmonyLib; using Aikido.Zen.Core.Models; using Aikido.Zen.Core.Helpers; +using Aikido.Zen.Core; namespace Aikido.Zen.DotNetFramework.Patches { @@ -27,6 +28,14 @@ public static void ApplyPatches(Harmony harmony) PatchMethod(harmony, "System.Data.SqlClient", "SqlCommand", "ExecuteScalar"); PatchMethod(harmony, "System.Data.SqlClient", "SqlCommand", "ExecuteReader", "System.Data.CommandBehavior"); + //SQL ServerCE + PatchMethod(harmony, "System.Data.SqlServerCe", "SqlCeCommand", "ExecuteNonQuery"); + PatchMethod(harmony, "System.Data.SqlServerCe", "SqlCeCommand", "ExecuteScalar"); + PatchMethod(harmony, "System.Data.SqlServerCe", "SqlCeCommand", "ExecuteReader", "System.Data.CommandBehavior"); + PatchMethod(harmony, "System.Data.SqlServerCe", "SqlCeCommand", "ExecuteNonQuery"); + PatchMethod(harmony, "System.Data.SqlServerCe", "SqlCeCommand", "ExecuteScalar"); + PatchMethod(harmony, "System.Data.SqlServerCe", "SqlCeCommand", "ExecuteReader", "System.Data.CommandBehavior"); + // SQLite PatchMethod(harmony, "Microsoft.Data.Sqlite", "SqliteCommand", "ExecuteNonQuery"); PatchMethod(harmony, "Microsoft.Data.Sqlite", "SqliteCommand", "ExecuteScalar"); @@ -50,6 +59,11 @@ public static void ApplyPatches(Harmony harmony) PatchMethod(harmony, "MySqlX", "XDevAPI.Relational.Table", "Insert"); PatchMethod(harmony, "MySqlX", "XDevAPI.Relational.Table", "Update"); PatchMethod(harmony, "MySqlX", "XDevAPI.Relational.Table", "Delete"); + + // NPoco + PatchMethod(harmony, "NPoco", "Database", "ExecuteReaderHelper", "System.Data.Common.DbCommand"); + PatchMethod(harmony, "NPoco", "Database", "ExecuteNonQueryHelper", "System.Data.Common.DbCommand"); + PatchMethod(harmony, "NPoco", "Database", "ExecuteScalarHelper", "System.Data.Common.DbCommand"); } /// @@ -66,6 +80,7 @@ private static void PatchMethod(Harmony harmony, string assemblyName, string typ if (method != null) { harmony.Patch(method, new HarmonyMethod(typeof(SqlClientPatches).GetMethod(nameof(OnCommandExecuting), BindingFlags.Static | BindingFlags.NonPublic))); + Agent.Instance.Context.Patches.Add($"{assemblyName}.{typeName}.{methodName}"); } } @@ -78,7 +93,8 @@ private static void PatchMethod(Harmony harmony, string assemblyName, string typ /// True if the original method should continue execution; otherwise, false. private static bool OnCommandExecuting(object[] __args, MethodBase __originalMethod, object __instance) { - var dbCommand = __instance as System.Data.Common.DbCommand; + var dbCommand = __instance as System.Data.Common.DbCommand + ?? __args[0] as System.Data.Common.DbCommand; if (dbCommand == null) return true; var assembly = __instance.GetType().Assembly.FullName?.Split(new[] { ", Culture=" }, StringSplitOptions.RemoveEmptyEntries)[0]; return Aikido.Zen.Core.Patches.SqlClientPatcher.OnCommandExecuting(__args, __originalMethod, dbCommand, assembly, Zen.GetContext()); From a42960b80fcb14852f71678582fb87ecf36b6922 Mon Sep 17 00:00:00 2001 From: Yannis Standaert Date: Mon, 20 Jan 2025 17:41:29 +0100 Subject: [PATCH 22/36] fixing nuget packages --- .../Aikido.Zen.DotNetCore.nuspec | 21 +++++++++---------- .../Aikido.Zen.DotNetCore.targets | 16 ++++++++++++++ .../Middleware/ContextMiddleware.cs | 7 ++++--- 3 files changed, 30 insertions(+), 14 deletions(-) create mode 100644 Aikido.Zen.DotNetCore/Aikido.Zen.DotNetCore.targets diff --git a/Aikido.Zen.DotNetCore/Aikido.Zen.DotNetCore.nuspec b/Aikido.Zen.DotNetCore/Aikido.Zen.DotNetCore.nuspec index 4d37aba7..3c159260 100644 --- a/Aikido.Zen.DotNetCore/Aikido.Zen.DotNetCore.nuspec +++ b/Aikido.Zen.DotNetCore/Aikido.Zen.DotNetCore.nuspec @@ -2,7 +2,7 @@ Aikido.Zen.DotNetCore - 0.0.1-alpha4 + 0.0.1-alpha5 $title$ Aikido Security Aikido Security @@ -51,15 +51,14 @@ - - - - - - - - - - + + + + + + + + + \ No newline at end of file diff --git a/Aikido.Zen.DotNetCore/Aikido.Zen.DotNetCore.targets b/Aikido.Zen.DotNetCore/Aikido.Zen.DotNetCore.targets new file mode 100644 index 00000000..f84a993f --- /dev/null +++ b/Aikido.Zen.DotNetCore/Aikido.Zen.DotNetCore.targets @@ -0,0 +1,16 @@ + + + + + PreserveNewest + + + + + + + + + + + \ No newline at end of file diff --git a/Aikido.Zen.DotNetCore/Middleware/ContextMiddleware.cs b/Aikido.Zen.DotNetCore/Middleware/ContextMiddleware.cs index 1e5fb9a4..92a3c0a5 100644 --- a/Aikido.Zen.DotNetCore/Middleware/ContextMiddleware.cs +++ b/Aikido.Zen.DotNetCore/Middleware/ContextMiddleware.cs @@ -2,6 +2,7 @@ using Aikido.Zen.Core.Helpers; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Routing; +using System.Collections.Concurrent; namespace Aikido.Zen.DotNetCore.Middleware { @@ -18,9 +19,9 @@ public ContextMiddleware(IEnumerable endpointSources) public async Task InvokeAsync(HttpContext httpContext, RequestDelegate next) { - // Convert headers and query parameters to dictionaries once - var queryDictionary = httpContext.Request.Query.ToDictionary(q => q.Key, q => q.Value.ToArray()); - var headersDictionary = httpContext.Request.Headers.ToDictionary(h => h.Key, h => h.Value.ToArray()); + // Convert headers and query parameters to thread-safe dictionaries + var queryDictionary = new ConcurrentDictionary(httpContext.Request.Query.ToDictionary(q => q.Key, q => q.Value.ToArray())); + var headersDictionary = new ConcurrentDictionary(httpContext.Request.Headers.ToDictionary(h => h.Key, h => h.Value.ToArray())); var context = new Context { From 6b8c500eb779b39e354eaefb2c57443a23798f11 Mon Sep 17 00:00:00 2001 From: Yannis Standaert Date: Tue, 21 Jan 2025 10:40:09 +0100 Subject: [PATCH 23/36] improvements to the cake and release scripts --- .github/workflows/release.yml | 20 ++++++++++++++------ build.cake | 14 +++++++++----- 2 files changed, 23 insertions(+), 11 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index b32fb1ab..8d7b8921 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -12,12 +12,13 @@ jobs: env: DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true DOTNET_CLI_TELEMETRY_OPTOUT: true - CAKE_NUGETAPIKEY: ${{ secrets.NUGETAPIKEY }} steps: - - uses: actions/checkout@v4 + - name: Checkout code + uses: actions/checkout@v4 - - uses: actions/cache@v3 + - name: Cache NuGet packages + uses: actions/cache@v3 with: path: | ~/.nuget/packages @@ -46,10 +47,17 @@ jobs: run: dotnet tool install --global Cake.Tool - name: Run Cake Script to Build and Pack - run: dotnet cake build.cake --target=CreatePackages + run: | + TAG_NAME=${{ github.ref_name }} + dotnet cake build.cake --target=CreatePackages --libVersion=${{ github.ref_name }} - name: Publish NuGet Packages run: | - for %%f in (artifacts\*.nupkg) do ( - dotnet nuget push %%f --api-key ${{ secrets.NUGETAPIKEY }} --source https://api.nuget.org/v3/index.json + for %f in (artifacts\*.nupkg) do ( + dotnet nuget push %f --api-key ${{ secrets.NUGETAPIKEY }} --source https://api.nuget.org/v3/index.json + if errorlevel 1 ( + echo "Failed to push %f" + exit /b 1 + ) + echo "Pushed %f" ) diff --git a/build.cake b/build.cake index a867f169..c4ba1e58 100644 --- a/build.cake +++ b/build.cake @@ -6,9 +6,10 @@ var configuration = Argument("configuration", "Release"); var framework = Argument("framework", ""); var solution = "./Aikido.Zen.sln"; var projectName = "Aikido.Zen.Core"; -var version = "0.1.35"; +var zenInternalsVersion = "0.1.35"; +var libVersion = Argument("libVersion"); -var baseUrl = $"https://github.com/AikidoSec/zen-internals/releases/download/v{version}/"; +var baseUrl = $"https://github.com/AikidoSec/zen-internals/releases/download/v{zenInternalsVersion}/"; var librariesDir = $"./{projectName}/libraries"; var filesToDownload = new string[] { @@ -43,7 +44,7 @@ Task("DownloadLibraries") { FilePath file = files.First(); var currVersion = FileReadText(file).Split('-')[1]; - if (currVersion == version) + if (currVersion == zenInternalsVersion) { Information("Libraries already downloaded. skipping download."); return; @@ -81,7 +82,8 @@ Task("Build") DetailedSummary = false, NodeReuse = true } - .WithTarget("Build"); + .WithTarget("Build") + .WithProperty("version", libVersion); var projects = GetFiles("./**/*.csproj") .Where(p => !p.FullPath.Contains("sample-apps") && !p.FullPath.Contains("Aikido.Zen.Benchmarks")); @@ -174,11 +176,13 @@ Task("Pack") foreach (var project in projects) { - DotNetPack(project, new DotNetPackSettings + var specFile = project.Replace(".csproj", ".nuspec"); + DotNetPack(specFile, new DotNetPackSettings { Configuration = configuration, NoBuild = true, OutputDirectory = "./artifacts", + Version = libVersion }); } Information("Pack task completed successfully."); From 5318ceb06966d8f937f739f7f256ec99c2085eb7 Mon Sep 17 00:00:00 2001 From: Yannis Standaert Date: Tue, 21 Jan 2025 10:51:04 +0100 Subject: [PATCH 24/36] build.cake: replaced DotNetPack with NugetPack for improved package handling. --- build.cake | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/build.cake b/build.cake index c4ba1e58..67756796 100644 --- a/build.cake +++ b/build.cake @@ -177,10 +177,9 @@ Task("Pack") foreach (var project in projects) { var specFile = project.Replace(".csproj", ".nuspec"); - DotNetPack(specFile, new DotNetPackSettings + NugetPack(specFile, new NugetPackSettings { Configuration = configuration, - NoBuild = true, OutputDirectory = "./artifacts", Version = libVersion }); From badb5309021ff2d839664b192885113726e594ee Mon Sep 17 00:00:00 2001 From: Yannis Standaert Date: Tue, 21 Jan 2025 10:59:10 +0100 Subject: [PATCH 25/36] Added Cake.NuGet addin to build.cake for enhanced NuGet package management --- build.cake | 1 + 1 file changed, 1 insertion(+) diff --git a/build.cake b/build.cake index 67756796..a507151b 100644 --- a/build.cake +++ b/build.cake @@ -1,4 +1,5 @@ #addin nuget:?package=Cake.FileHelpers&version=6.0.0 +#addin nuget:?package=Cake.NuGet&version=6.0.0 var target = Argument("target", "Default"); From 542023a14146f587f98ff964998068aaf17ba772 Mon Sep 17 00:00:00 2001 From: Yannis Standaert Date: Tue, 21 Jan 2025 11:42:25 +0100 Subject: [PATCH 26/36] fixed the cakescript --- Aikido.Zen.DotNetCore/Aikido.Zen.DotNetCore.nuspec | 2 +- .../Aikido.Zen.DotNetFramework.nuspec | 2 +- build.cake | 13 +++++++------ dotnet-tools.json | 12 +++++------- 4 files changed, 14 insertions(+), 15 deletions(-) diff --git a/Aikido.Zen.DotNetCore/Aikido.Zen.DotNetCore.nuspec b/Aikido.Zen.DotNetCore/Aikido.Zen.DotNetCore.nuspec index 3c159260..9d3556f7 100644 --- a/Aikido.Zen.DotNetCore/Aikido.Zen.DotNetCore.nuspec +++ b/Aikido.Zen.DotNetCore/Aikido.Zen.DotNetCore.nuspec @@ -2,7 +2,7 @@ Aikido.Zen.DotNetCore - 0.0.1-alpha5 + * $title$ Aikido Security Aikido Security diff --git a/Aikido.Zen.DotNetFramework/Aikido.Zen.DotNetFramework.nuspec b/Aikido.Zen.DotNetFramework/Aikido.Zen.DotNetFramework.nuspec index d217ac70..87a208ab 100644 --- a/Aikido.Zen.DotNetFramework/Aikido.Zen.DotNetFramework.nuspec +++ b/Aikido.Zen.DotNetFramework/Aikido.Zen.DotNetFramework.nuspec @@ -2,7 +2,7 @@ Aikido.Zen.DotNetFramework - 0.0.1-alpha4 + * $title$ Aikido Security Aikido Security diff --git a/build.cake b/build.cake index a507151b..09de5342 100644 --- a/build.cake +++ b/build.cake @@ -1,5 +1,6 @@ #addin nuget:?package=Cake.FileHelpers&version=6.0.0 -#addin nuget:?package=Cake.NuGet&version=6.0.0 +#load "nuget:https://www.nuget.org/api/v2?package=Cake.NuGet&version=5.0.0" + var target = Argument("target", "Default"); @@ -8,7 +9,7 @@ var framework = Argument("framework", ""); var solution = "./Aikido.Zen.sln"; var projectName = "Aikido.Zen.Core"; var zenInternalsVersion = "0.1.35"; -var libVersion = Argument("libVersion"); +var libVersion = Argument("libVersion", "0.0.1-alpha5"); var baseUrl = $"https://github.com/AikidoSec/zen-internals/releases/download/v{zenInternalsVersion}/"; var librariesDir = $"./{projectName}/libraries"; @@ -178,12 +179,12 @@ Task("Pack") foreach (var project in projects) { var specFile = project.Replace(".csproj", ".nuspec"); - NugetPack(specFile, new NugetPackSettings + var nugetPackSettings = new NuGetPackSettings { - Configuration = configuration, OutputDirectory = "./artifacts", - Version = libVersion - }); + Version = libVersion, + }; + NuGetPack(specFile, nugetPackSettings); } Information("Pack task completed successfully."); } diff --git a/dotnet-tools.json b/dotnet-tools.json index 7b346950..99a3eb1c 100644 --- a/dotnet-tools.json +++ b/dotnet-tools.json @@ -2,11 +2,9 @@ "version": 1, "isRoot": true, "tools": { - "cake.tool": { - "version": "4.0.0", - "commands": [ - "dotnet-cake" - ] - } + "cake.tool": { + "version": "5.0.0", + "commands": ["dotnet-cake"] + } } - } \ No newline at end of file +} From ba942daaf3a035a1f8261ac1c8a46dac832f429d Mon Sep 17 00:00:00 2001 From: Yannis Standaert Date: Tue, 21 Jan 2025 11:56:09 +0100 Subject: [PATCH 27/36] fuzzy versioning for dotnet patch versions --- .github/workflows/release.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 8d7b8921..0a182d41 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -31,9 +31,9 @@ jobs: uses: actions/setup-dotnet@v3 with: dotnet-version: | - 4.6.1 - 4.7.2 - 4.8.2 + 4.6.x + 4.7.x + 4.8.x 6.0.x 7.0.x 8.0.x From 9271f7ade99464a8aeb8d740af9c28666d8d006e Mon Sep 17 00:00:00 2001 From: Yannis Standaert Date: Tue, 21 Jan 2025 12:06:37 +0100 Subject: [PATCH 28/36] specific version for .net framework --- .github/workflows/release.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 0a182d41..6c068a2e 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -31,9 +31,9 @@ jobs: uses: actions/setup-dotnet@v3 with: dotnet-version: | - 4.6.x - 4.7.x - 4.8.x + 4.6.2 + 4.7.2 + 4.8.1 6.0.x 7.0.x 8.0.x From 2c824b717fad490cec226135d005081aeedf4f5a Mon Sep 17 00:00:00 2001 From: Yannis Standaert Date: Tue, 21 Jan 2025 12:11:22 +0100 Subject: [PATCH 29/36] trying to fix the dotnetversion isntalls --- .github/workflows/release.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 6c068a2e..573becee 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -28,15 +28,15 @@ jobs: ${{ runner.os }}-nuget- - name: Setup .NET - uses: actions/setup-dotnet@v3 + uses: actions/setup-dotnet@v4 with: dotnet-version: | - 4.6.2 - 4.7.2 - 4.8.1 - 6.0.x - 7.0.x - 8.0.x + 4.6 + 4.7 + 4.8 + 6.0 + 7.0 + 8.0 - name: Add msbuild to PATH uses: microsoft/setup-msbuild@v2 From 7fdd9e8e65ec68f78859f52bd734ddc9047768ad Mon Sep 17 00:00:00 2001 From: Yannis Standaert Date: Tue, 21 Jan 2025 12:19:14 +0100 Subject: [PATCH 30/36] removed .net 4.6 --- .github/workflows/release.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 573becee..d5148d07 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -31,7 +31,6 @@ jobs: uses: actions/setup-dotnet@v4 with: dotnet-version: | - 4.6 4.7 4.8 6.0 From 5ec2ec72c43ccd4b10eb213a7805e2f75510a20b Mon Sep 17 00:00:00 2001 From: Yannis Standaert Date: Tue, 21 Jan 2025 12:30:47 +0100 Subject: [PATCH 31/36] Remove .NET 4.7 and 4.8 from release workflow, retaining only .NET 6.0, 7.0, and 8.0 versions for streamlined version management. --- .github/workflows/release.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index d5148d07..0b5c9ba6 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -31,8 +31,6 @@ jobs: uses: actions/setup-dotnet@v4 with: dotnet-version: | - 4.7 - 4.8 6.0 7.0 8.0 From 1d19f8719aae7a4f2a20c6a33f0ec3eb8c0c2a35 Mon Sep 17 00:00:00 2001 From: Yannis Standaert Date: Tue, 21 Jan 2025 12:38:37 +0100 Subject: [PATCH 32/36] Refactor release workflow to simplify Cake script execution by removing unnecessary line breaks in the build command. --- .github/workflows/release.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 0b5c9ba6..71b4c328 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -44,9 +44,7 @@ jobs: run: dotnet tool install --global Cake.Tool - name: Run Cake Script to Build and Pack - run: | - TAG_NAME=${{ github.ref_name }} - dotnet cake build.cake --target=CreatePackages --libVersion=${{ github.ref_name }} + run: dotnet cake build.cake --target=CreatePackages --libVersion=${{ github.ref_name }} - name: Publish NuGet Packages run: | From d0517a1a128698617957a2ec55700f1f0855d549 Mon Sep 17 00:00:00 2001 From: Yannis Standaert Date: Tue, 21 Jan 2025 12:43:08 +0100 Subject: [PATCH 33/36] Enhance release workflow by adding dependency installation step for .NET tools --- .github/workflows/release.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 71b4c328..027369a1 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -40,6 +40,11 @@ jobs: with: vs-version: "[17.2,19.0)" + - name: Install dependencies + run: | + dotnet tool restore + dotnet restore + - name: Install Cake Tool run: dotnet tool install --global Cake.Tool From a3ade0b2f614b170b8d915ee2f655b07ef109577 Mon Sep 17 00:00:00 2001 From: Yannis Standaert Date: Tue, 21 Jan 2025 12:51:35 +0100 Subject: [PATCH 34/36] Update task dependencies in build.cake to streamline package creation process by replacing 'Test' and 'TestE2E' with 'Build' as a prerequisite for 'CreatePackages'. --- build.cake | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/build.cake b/build.cake index 09de5342..2c787326 100644 --- a/build.cake +++ b/build.cake @@ -195,8 +195,7 @@ Task("Pack") }); Task("CreatePackages") - .IsDependentOn("Test") - .IsDependentOn("TestE2E") + .IsDependentOn("Build") .IsDependentOn("Pack"); Task("Default") From cbed23410145e7e1eb322af651f5ec09d1528037 Mon Sep 17 00:00:00 2001 From: Yannis Standaert Date: Tue, 21 Jan 2025 13:05:25 +0100 Subject: [PATCH 35/36] Refactor NuGet package publishing in release workflow to use PowerShell for improved error handling and clarity --- .github/workflows/release.yml | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 027369a1..daa82f81 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -53,11 +53,13 @@ jobs: - name: Publish NuGet Packages run: | - for %f in (artifacts\*.nupkg) do ( - dotnet nuget push %f --api-key ${{ secrets.NUGETAPIKEY }} --source https://api.nuget.org/v3/index.json - if errorlevel 1 ( - echo "Failed to push %f" - exit /b 1 - ) - echo "Pushed %f" - ) + $ErrorActionPreference = "Stop" + Get-ChildItem -Path artifacts\*.nupkg | ForEach-Object { + try { + dotnet nuget push $_.FullName --api-key ${{ secrets.NUGETAPIKEY }} --source https://api.nuget.org/v3/index.json + Write-Host "Pushed $($_.FullName)" + } catch { + Write-Host "Failed to push $($_.FullName)" + exit 1 + } + } From 53cd844eeeefc4a592cd1203846875dd5187ee39 Mon Sep 17 00:00:00 2001 From: Yannis Standaert Date: Tue, 21 Jan 2025 13:31:28 +0100 Subject: [PATCH 36/36] PR comments --- .github/workflows/release.yml | 2 +- Aikido.Zen.Core/Models/AgentContext.cs | 2 -- Aikido.Zen.DotNetFramework/Patches/SqlClientPatches.cs | 1 - 3 files changed, 1 insertion(+), 4 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index daa82f81..90dac795 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -27,7 +27,7 @@ jobs: restore-keys: | ${{ runner.os }}-nuget- - - name: Setup .NET + - name: Install .NET versions that we need for building the library uses: actions/setup-dotnet@v4 with: dotnet-version: | diff --git a/Aikido.Zen.Core/Models/AgentContext.cs b/Aikido.Zen.Core/Models/AgentContext.cs index 017374f1..231615da 100644 --- a/Aikido.Zen.Core/Models/AgentContext.cs +++ b/Aikido.Zen.Core/Models/AgentContext.cs @@ -27,8 +27,6 @@ public class AgentContext private long _started = DateTimeHelper.UTCNowUnixMilliseconds(); public long ConfigLastUpdated { get; set; } = 0; - public IList Patches { get; set; } = new List(); - public void AddRequest() { diff --git a/Aikido.Zen.DotNetFramework/Patches/SqlClientPatches.cs b/Aikido.Zen.DotNetFramework/Patches/SqlClientPatches.cs index b0576e27..fbcb992e 100644 --- a/Aikido.Zen.DotNetFramework/Patches/SqlClientPatches.cs +++ b/Aikido.Zen.DotNetFramework/Patches/SqlClientPatches.cs @@ -80,7 +80,6 @@ private static void PatchMethod(Harmony harmony, string assemblyName, string typ if (method != null) { harmony.Patch(method, new HarmonyMethod(typeof(SqlClientPatches).GetMethod(nameof(OnCommandExecuting), BindingFlags.Static | BindingFlags.NonPublic))); - Agent.Instance.Context.Patches.Add($"{assemblyName}.{typeName}.{methodName}"); } }