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 @@ - +