diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
new file mode 100644
index 0000000000..4e6a92c443
--- /dev/null
+++ b/.pre-commit-config.yaml
@@ -0,0 +1 @@
+repos: []
diff --git a/.vscode/settings.json b/.vscode/settings.json
index 65ff848758..7071f75b3c 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -18,5 +18,9 @@
"scripts/customizing/app_data_import",
"-p",
"test_*.py"
- ]
+ ],
+ "sonarlint.connectedMode.project": {
+ "connectionId": "cactusesecurity",
+ "projectKey": "CactuseSecurity_firewall-orchestrator"
+ }
}
diff --git a/documentation/installer/install-advanced.md b/documentation/installer/install-advanced.md
index a93dd13fff..04cbcf61a2 100644
--- a/documentation/installer/install-advanced.md
+++ b/documentation/installer/install-advanced.md
@@ -77,30 +77,40 @@ If you use authentication:
Note that the following domains must be reachable through the proxy:
- cactus.de (only for downloading test data, not needed if run with "--skip-tags test")
ubuntu.com
canonical.com
github.com
+ api.github.com
githubusercontent.com
docker.com
cloudflare.docker.com
docker.io
+ auth.docker.io
hasura.io
+ releases.hasura.io
postgresql.org
microsoft.com
nuget.org
+ api.nuget.org
googlechromelabs.github.io
storage.googleapis.com
pypi.org
- pythonhosted.org (and sub-domains)
+ pythonhosted.org
+ files.pythonhosted.org
snapcraft.io
+ api.snapcraft.io
snapcraftcontent.com (and sub-domains)
+ cactus.de (and sub-domains, only for downloading test data, not needed if run with "--skip-tags test")
-NB: for vscode-debugging, you also need access to
-
+#### For vscode-debugging only - most are needed for downloading extensions
visualstudio.com
-
-
+ vsassets.io (and subdomains)
+ digicert.com (and subdomains)
+ dot.net (and subdomains)
+ windows.net (and subdomains)
+ applicationinsights.azure.com (and subdomains)
+ exp-tas.com (and subdomains)
+
#### Pyhton proxy config
Remember if your server resides behind a proxy that you will have to set the proxy for pip as follows before installing ansible:
diff --git a/roles/lib/files/FWO.Api.Client/FWO.Api.Client.csproj b/roles/lib/files/FWO.Api.Client/FWO.Api.Client.csproj
index 1d279b22ed..d0a5164ba2 100644
--- a/roles/lib/files/FWO.Api.Client/FWO.Api.Client.csproj
+++ b/roles/lib/files/FWO.Api.Client/FWO.Api.Client.csproj
@@ -13,8 +13,8 @@
-
-
+
+
diff --git a/roles/lib/files/FWO.Config.File/FWO.Config.File.csproj b/roles/lib/files/FWO.Config.File/FWO.Config.File.csproj
index 8cf70d18d1..04d8e7cdce 100644
--- a/roles/lib/files/FWO.Config.File/FWO.Config.File.csproj
+++ b/roles/lib/files/FWO.Config.File/FWO.Config.File.csproj
@@ -7,7 +7,7 @@
-
+
diff --git a/roles/lib/files/FWO.Mail/FWO.Mail.csproj b/roles/lib/files/FWO.Mail/FWO.Mail.csproj
index 5025dcdbdd..60c6e8e069 100644
--- a/roles/lib/files/FWO.Mail/FWO.Mail.csproj
+++ b/roles/lib/files/FWO.Mail/FWO.Mail.csproj
@@ -10,7 +10,7 @@
-
+
diff --git a/roles/lib/files/FWO.Report/FWO.Report.csproj b/roles/lib/files/FWO.Report/FWO.Report.csproj
index a32ce5cb95..fe3a225796 100644
--- a/roles/lib/files/FWO.Report/FWO.Report.csproj
+++ b/roles/lib/files/FWO.Report/FWO.Report.csproj
@@ -8,7 +8,7 @@
-
+
diff --git a/roles/lib/files/FWO.Services/AppServerHelper.cs b/roles/lib/files/FWO.Services/AppServerHelper.cs
index 8b9de7c2e4..95e614f7db 100644
--- a/roles/lib/files/FWO.Services/AppServerHelper.cs
+++ b/roles/lib/files/FWO.Services/AppServerHelper.cs
@@ -22,7 +22,7 @@ public static async Task ConstructAppServerNameFromDns(ModellingAppServe
{
if (logUnresolvable)
{
- Log.WriteWarning("Import App Server Data", $"Found empty (unresolvable) IP {appServer.Ip}");
+ Log.WriteDebug("Import App Server Data", $"Found empty (unresolvable) IP {appServer.Ip}");
}
}
else
diff --git a/roles/lib/files/chrome/last-known-good-versions-with-downloads.json b/roles/lib/files/chrome/last-known-good-versions-with-downloads.json
new file mode 100644
index 0000000000..604f35744f
--- /dev/null
+++ b/roles/lib/files/chrome/last-known-good-versions-with-downloads.json
@@ -0,0 +1,19 @@
+{
+ "timestamp": "2024-11-15T00:00:00Z",
+ "channels": {
+ "Stable": {
+ "channel": "Stable",
+ "version": "128.0.6613.137",
+ "revision": "1188749",
+ "downloads": {
+ "chrome": [
+ {
+ "platform": "linux64",
+ "url": "https://storage.googleapis.com/chrome-for-testing-public/128.0.6613.137/linux64/chrome-linux64.zip",
+ "revision": "1188749"
+ }
+ ]
+ }
+ }
+ }
+}
diff --git a/roles/lib/tasks/install_puppeteer.yml b/roles/lib/tasks/install_puppeteer.yml
index bdbfddd431..8d1d4d43f9 100644
--- a/roles/lib/tasks/install_puppeteer.yml
+++ b/roles/lib/tasks/install_puppeteer.yml
@@ -85,23 +85,39 @@
environment: "{{ proxy_env }}"
# get google chrome for pdf generation
-- block:
- - name: get last known good versions (primary)
- uri:
- url: https://googlechromelabs.github.io/chrome-for-testing/last-known-good-versions-with-downloads.json
- return_content: true
- register: chrome_versions
- become: false
-
- rescue:
- - name: fallback - get last known good versions (raw.githubusercontent.com)
- uri:
- url: https://raw.githubusercontent.com/GoogleChromeLabs/chrome-for-testing/main/data/last-known-good-versions-with-downloads.json
- return_content: true
- headers:
- Accept: application/json
- register: chrome_versions
- become: false
+- name: get last known good versions (primary)
+ uri:
+ url: https://googlechromelabs.github.io/chrome-for-testing/last-known-good-versions-with-downloads.json
+ return_content: true
+ register: chrome_versions_primary
+ failed_when: false
+ become: false
+ environment: "{{ proxy_env }}"
+
+- name: get last known good versions (github api raw)
+ uri:
+ url: https://api.github.com/repos/GoogleChromeLabs/chrome-for-testing/contents/data/last-known-good-versions-with-downloads.json?ref=main
+ headers:
+ Accept: application/vnd.github.v3.raw
+ return_content: true
+ register: chrome_versions_github_api
+ failed_when: false
+ become: false
+ environment: "{{ proxy_env }}"
+
+- name: pick chrome metadata source (primary -> github api)
+ set_fact:
+ chrome_versions: >-
+ {{
+ chrome_versions_primary
+ if (chrome_versions_primary.status | default(-1)) == 200 else
+ chrome_versions_github_api
+ }}
+
+- name: fail when no chrome metadata available
+ fail:
+ msg: "Could not fetch Chrome for Testing version metadata via primary URL or GitHub API."
+ when: chrome_versions.status | default(-1) != 200
# Parse once, regardless of Content-Type
- name: normalize/parse JSON response
diff --git a/roles/middleware/files/FWO.Middleware.Server/FWO.Middleware.Server.csproj b/roles/middleware/files/FWO.Middleware.Server/FWO.Middleware.Server.csproj
index d99f24106f..a1dd6871b5 100644
--- a/roles/middleware/files/FWO.Middleware.Server/FWO.Middleware.Server.csproj
+++ b/roles/middleware/files/FWO.Middleware.Server/FWO.Middleware.Server.csproj
@@ -10,8 +10,8 @@
-
-
+
+
diff --git a/roles/middleware/files/FWO.Middleware.Server/LdapBasic.cs b/roles/middleware/files/FWO.Middleware.Server/LdapBasic.cs
index 6f8ebb7774..e7817d3903 100644
--- a/roles/middleware/files/FWO.Middleware.Server/LdapBasic.cs
+++ b/roles/middleware/files/FWO.Middleware.Server/LdapBasic.cs
@@ -594,7 +594,7 @@ private static bool IsFullyQualifiedDn(string name)
/// true if user added
public async Task AddUserToEntry(string userDn, string entry)
{
- Log.WriteInfo("Add User to Entry", $"Trying to add User: \"{userDn}\" to Entry: \"{entry}\"");
+ Log.WriteDebug("Add User to Entry", $"Trying to add User: \"{userDn}\" to Entry: \"{entry}\"");
return await ModifyUserInEntry(userDn, entry, LdapModification.Add);
}
diff --git a/roles/middleware/files/FWO.Middleware.Server/Program.cs b/roles/middleware/files/FWO.Middleware.Server/Program.cs
index b3e8260abd..3430e1e8ce 100644
--- a/roles/middleware/files/FWO.Middleware.Server/Program.cs
+++ b/roles/middleware/files/FWO.Middleware.Server/Program.cs
@@ -5,7 +5,7 @@
using FWO.Middleware.Server;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
-using Microsoft.OpenApi.Models;
+using Microsoft.OpenApi;
using System.Reflection;
// Implicitly call static constructor so background lock process is started
diff --git a/roles/middleware/templates/fworch-middleware.service.j2 b/roles/middleware/templates/fworch-middleware.service.j2
index e0853016fc..b64f6c5d8b 100644
--- a/roles/middleware/templates/fworch-middleware.service.j2
+++ b/roles/middleware/templates/fworch-middleware.service.j2
@@ -12,6 +12,6 @@ ExecStart={{ middleware_server_start_dir }}/bin/{{ dotnet_mode }}/net{{ dotnet_v
Restart=on-failure
SyslogIdentifier={{ middleware_server_syslog_id }}
User={{ fworch_user }}
-Environment=
+Environment="PYTHONPATH={{ fworch_home }}"
[Install]
WantedBy=multi-user.target
diff --git a/roles/tests-unit/files/FWO.Test/FWO.Test.csproj b/roles/tests-unit/files/FWO.Test/FWO.Test.csproj
index 0d41219454..77d56862d8 100644
--- a/roles/tests-unit/files/FWO.Test/FWO.Test.csproj
+++ b/roles/tests-unit/files/FWO.Test/FWO.Test.csproj
@@ -1,4 +1,4 @@
-
+
net8.0
@@ -8,12 +8,12 @@
-
-
+
+
-
-
-
+
+
+
diff --git a/roles/tests-unit/files/FWO.Test/UiRsbLinkTest.cs b/roles/tests-unit/files/FWO.Test/UiRsbLinkTest.cs
index e90f297ec4..5623776b2e 100644
--- a/roles/tests-unit/files/FWO.Test/UiRsbLinkTest.cs
+++ b/roles/tests-unit/files/FWO.Test/UiRsbLinkTest.cs
@@ -1,4 +1,3 @@
-
using AngleSharp.Css.Dom;
using AngleSharp.Dom;
using Bunit;
@@ -12,13 +11,11 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.JSInterop;
using NUnit.Framework;
-using System.Text.RegularExpressions;
-using System.Threading.Tasks;
namespace FWO.Test
{
[FixtureLifeCycle(LifeCycle.InstancePerTestCase)]
- public class UiRsbLinkTest : Bunit.TestContext
+ public class UiRsbLinkTest : BunitContext
{
static readonly UserConfig userConfig = new SimulatedUserConfig
{
@@ -41,25 +38,25 @@ public async Task ObjShouldBeVisibleAfterNavigation()
Services.AddScoped(_ => JSInterop.JSRuntime);
Services.AddLocalization();
- var objToFind = currentReport.ReportData.ManagementData[0].Objects[1];
- var hrefValue = ReportDevicesBase.GetReportDevicesLinkAddress(OutputLocation.report, currentReport.ReportData.ManagementData[0].Id, ObjCatString.NwObj, 0, objToFind.Id, currentReport.ReportType);
- var link = $"https://localhost/{hrefValue}";
+ Data.NetworkObject objToFind = currentReport.ReportData.ManagementData[0].Objects[1];
+ string hrefValue = ReportDevicesBase.GetReportDevicesLinkAddress(OutputLocation.report, currentReport.ReportData.ManagementData[0].Id, ObjCatString.NwObj, 0, objToFind.Id, currentReport.ReportType);
+ string link = $"https://localhost/{hrefValue}";
- var navigationManager = Services.GetRequiredService();
+ BunitNavigationManager navigationManager = Services.GetRequiredService();
navigationManager.NavigateTo(link);
// Mock JS interop
JSInterop.Setup("getCurrentUrl").SetResult(link);
- var scrollIntoRSBViewInvocation = JSInterop.Setup("scrollIntoRSBView", _ => true).SetResult(true);
- var removeUrlFragmentInvocation = JSInterop.SetupVoid("removeUrlFragment");
+ JSRuntimeInvocationHandler scrollIntoRSBViewInvocation = JSInterop.Setup("scrollIntoRSBView", _ => true).SetResult(true);
+ JSRuntimeInvocationHandler removeUrlFragmentInvocation = JSInterop.SetupVoid("removeUrlFragment");
// Act
- var cut = RenderComponent(parameters => parameters
+ IRenderedComponent cut = Render(parameters => parameters
.Add(p => p.CurrentReport, currentReport)
.Add(p => p.SelectedRules, [currentReport.ReportData.ManagementData[0].Devices[0].Rules![0]]));
// manually trigger
- var anchorNavToRSB = cut.FindComponent();
+ IRenderedComponent anchorNavToRSB = cut.FindComponent();
Task timeout = Task.Delay(2000);
Task scrollTask = anchorNavToRSB.InvokeAsync(() => anchorNavToRSB.Instance.ScrollToFragment());
Task completedTask = await Task.WhenAny(scrollTask, timeout);
@@ -69,12 +66,12 @@ public async Task ObjShouldBeVisibleAfterNavigation()
}
// Assert
Assert.That(scrollIntoRSBViewInvocation.Invocations, Is.Not.Empty, "scrollIntoRSBView should have been called");
- var invocation = scrollIntoRSBViewInvocation.Invocations.First();
- var parameter = invocation.Arguments[0];
+ JSRuntimeInvocation invocation = scrollIntoRSBViewInvocation.Invocations.First();
+ object? parameter = invocation.Arguments[0];
Assert.That(parameter, Is.Not.Null, "scrollIntoRSBView was called with a null parameter");
Assert.That(parameter, Is.InstanceOf(), "scrollIntoRSBView was called with a non-string parameter");
Assert.That((string)parameter!, Is.Not.Empty, "scrollIntoRSBView was called with an empty string");
- var element = cut.Find($"#{parameter}");
+ IElement element = cut.Find($"#{parameter}");
Assert.That(IsElementVisible(element), Is.True, "Element is not visible (might be incorrect tab or collapsed)");
}
@@ -82,8 +79,8 @@ private bool IsElementVisible(IElement? element)
{
while (element != null)
{
- var computedStyle = element.Owner?.DefaultView?.GetComputedStyle(element);
- var display = computedStyle?.GetPropertyValue("display");
+ ICssStyleDeclaration? computedStyle = element.Owner?.DefaultView?.GetComputedStyle(element);
+ string? display = computedStyle?.GetPropertyValue("display");
if (display == "none")
{
Log.WriteError("Test UI RSB", $"Element {element.TagName} is not visible");
diff --git a/roles/ui/files/FWO.UI/FWO.Ui.csproj b/roles/ui/files/FWO.UI/FWO.Ui.csproj
index bbd07b340c..93eacb121e 100644
--- a/roles/ui/files/FWO.UI/FWO.Ui.csproj
+++ b/roles/ui/files/FWO.UI/FWO.Ui.csproj
@@ -8,7 +8,7 @@
-
+