From c8f6f91695e3d7f1fde8a48194dbf0aaa60ce494 Mon Sep 17 00:00:00 2001 From: abarz722 Date: Fri, 22 Mar 2024 15:33:49 +0100 Subject: [PATCH 1/4] some fixes + cleanup --- .../FWO.Report.Filter/Ast/AstNodeFilterInt.cs | 3 +- .../Ast/AstNodeFilterString.cs | 9 ++- .../lib/files/FWO.Report/ReportConnections.cs | 10 ++- .../files/FWO.UI/Pages/Reporting/Report.razor | 61 ++++++++++--------- .../Reporting/Reports/ConnectionsReport.razor | 23 ++++--- roles/ui/files/FWO.UI/Shared/TabSet.razor | 4 +- roles/ui/files/FWO.UI/wwwroot/css/site.css | 2 +- 7 files changed, 64 insertions(+), 48 deletions(-) diff --git a/roles/lib/files/FWO.Report.Filter/Ast/AstNodeFilterInt.cs b/roles/lib/files/FWO.Report.Filter/Ast/AstNodeFilterInt.cs index 7043d2438..efa418c73 100644 --- a/roles/lib/files/FWO.Report.Filter/Ast/AstNodeFilterInt.cs +++ b/roles/lib/files/FWO.Report.Filter/Ast/AstNodeFilterInt.cs @@ -54,7 +54,8 @@ private DynGraphqlQuery ExtractDestinationPortFilter(DynGraphqlQuery query) string queryVarName = AddVariable(query, "dport", Operator.Kind, semanticValue); query.ruleWhereStatement += "rule_services: { service: { svcgrp_flats: { serviceBySvcgrpFlatMemberId: { svc_port: {_lte" + ": $" + queryVarName + "}, svc_port_end: {_gte: $" + queryVarName + " } } } } }"; - query.connectionWhereStatement += $"service_connections: {{service: {{port: {{ _lte: ${queryVarName} }}, port_end: {{ _gte: ${queryVarName} }} }} }}"; + query.connectionWhereStatement += $"_or: [ {{ service_connections: {{service: {{ port: {{ _lte: ${queryVarName} }}, port_end: {{ _gte: ${queryVarName} }} }} }} }}, " + + $"{{ service_group_connections: {{service_group: {{ service_service_groups: {{ service: {{ port: {{ _lte: ${queryVarName} }}, port_end: {{ _gte: ${queryVarName} }} }} }} }} }} }} ]"; return query; } diff --git a/roles/lib/files/FWO.Report.Filter/Ast/AstNodeFilterString.cs b/roles/lib/files/FWO.Report.Filter/Ast/AstNodeFilterString.cs index f22701fbd..cf9ba9041 100644 --- a/roles/lib/files/FWO.Report.Filter/Ast/AstNodeFilterString.cs +++ b/roles/lib/files/FWO.Report.Filter/Ast/AstNodeFilterString.cs @@ -123,7 +123,8 @@ private DynGraphqlQuery ExtractProtocolFilter(DynGraphqlQuery query) { string queryVarName = AddVariable(query, "proto", Operator.Kind, semanticValue!); query.ruleWhereStatement += $"rule_services: {{service: {{stm_ip_proto: {{ip_proto_name: {{ {ExtractOperator()}: ${queryVarName} }} }} }} }}"; - query.connectionWhereStatement += $"service_connections: {{service: {{stm_ip_proto: {{ip_proto_name: {{ {ExtractOperator()}: ${queryVarName} }} }} }} }}"; + query.connectionWhereStatement += $"_or: [ {{ service_connections: {{service: {{stm_ip_proto: {{ip_proto_name: {{ {ExtractOperator()}: ${queryVarName} }} }} }} }} }}, " + + $"{{ service_group_connections: {{service_group: {{ service_service_groups: {{ service: {{ stm_ip_proto: {{ip_proto_name: {{ {ExtractOperator()}: ${queryVarName} }} }} }} }} }} }} }} ]"; return query; } @@ -137,8 +138,10 @@ private DynGraphqlQuery ExtractActionFilter(DynGraphqlQuery query) private DynGraphqlQuery ExtractServiceFilter(DynGraphqlQuery query) { string queryVarName = AddVariable(query, "svc", Operator.Kind, semanticValue!); - query.ruleWhereStatement += $"rule_services: {{ service: {{svcgrp_flats: {{serviceBySvcgrpFlatMemberId: {{svc_name: {{ {ExtractOperator()}: ${queryVarName} }} }} }} }} }} "; - query.connectionWhereStatement += $"_or: [ {{ service_connections: {{service: {{name: {{ {ExtractOperator()}: ${queryVarName} }} }} }} }}, {{ service_group_connections: {{service_group: {{name: {{ {ExtractOperator()}: ${queryVarName} }} }} }} }} ]"; + query.ruleWhereStatement += $"rule_services: {{ service: {{ svcgrp_flats: {{ serviceBySvcgrpFlatMemberId: {{ svc_name: {{ {ExtractOperator()}: ${queryVarName} }} }} }} }} }} "; + query.connectionWhereStatement += $"_or: [ {{ service_connections: {{ service: {{ name: {{ {ExtractOperator()}: ${queryVarName} }} }} }} }}, " + + $"{{ service_group_connections: {{service_group: {{ _or: [ {{ name: {{ {ExtractOperator()}: ${queryVarName} }} }}, " + + $"{{ service_service_groups: {{ service: {{ name: {{ {ExtractOperator()}: ${queryVarName} }} }} }} }} ] }} }} }} ]"; return query; } } diff --git a/roles/lib/files/FWO.Report/ReportConnections.cs b/roles/lib/files/FWO.Report/ReportConnections.cs index 49be4f77c..3b98c1c81 100644 --- a/roles/lib/files/FWO.Report/ReportConnections.cs +++ b/roles/lib/files/FWO.Report/ReportConnections.cs @@ -135,7 +135,10 @@ private void AppendNetworkObjectsHtml(List networkObjects, ref St { report.AppendLine($"

{userConfig.GetText("network_objects")}

"); report.AppendLine(""); - AppendNWObjHeadlineHtml(ref report); + if(networkObjects.Count > 0) + { + AppendNWObjHeadlineHtml(ref report); + } foreach (var nwObj in networkObjects) { report.AppendLine(""); @@ -164,7 +167,10 @@ private void AppendNetworkServicesHtml(List networkServices, ref { report.AppendLine($"

{userConfig.GetText("network_services")}

"); report.AppendLine("
"); - AppendNWSvcHeadlineHtml(ref report); + if(networkServices.Count > 0) + { + AppendNWSvcHeadlineHtml(ref report); + } foreach (var svc in networkServices) { report.AppendLine(""); diff --git a/roles/ui/files/FWO.UI/Pages/Reporting/Report.razor b/roles/ui/files/FWO.UI/Pages/Reporting/Report.razor index f740a18b3..540b7e6f0 100644 --- a/roles/ui/files/FWO.UI/Pages/Reporting/Report.razor +++ b/roles/ui/files/FWO.UI/Pages/Reporting/Report.razor @@ -127,7 +127,7 @@ break; case ReportType.Connections: - + break; default: @@ -136,18 +136,15 @@ } - @if (currentReport != null) + @if (currentReport != null && reportGenerationDuration != 0) { - if (reportGenerationDuration != 0) + if (reportGenerationDuration < 600) { - if (reportGenerationDuration < 600) - { - @(userConfig.GetText("report_duration")) @reportGenerationDuration.ToString("0.00") @(userConfig.GetText("seconds")). - } - else - { - @(userConfig.GetText("report_duration")) @((reportGenerationDuration/60.0).ToString("0.00")) @(userConfig.GetText("minutes")). - } + @(userConfig.GetText("report_duration")) @reportGenerationDuration.ToString("0.00") @(userConfig.GetText("seconds")). + } + else + { + @(userConfig.GetText("report_duration")) @((reportGenerationDuration/60.0).ToString("0.00")) @(userConfig.GetText("minutes")). } } @@ -158,7 +155,6 @@ AllTabVisible="(tenantFilteringAllowed && actReportFilters.SelectedTenant == null)" SelectedReportType = "actReportFilters.ReportType"/> - } @* ==== POPUPS ==== *@ @@ -179,14 +175,13 @@ public string? AppId { get; set; } public double reportGenerationDuration; - DateTime startTime = DateTime.Now; private bool processing = false; private CancellationTokenSource tokenSource = new CancellationTokenSource(); private List selectedItemsRuleReportTable = new List(); private List selectedItemsChangeReportTable = new List(); - private ModellingAppHandler? appHandler; + private List appHandlers = new(); List relevantManagementIds = new (); private ReportFilters actReportFilters = new (); @@ -285,6 +280,7 @@ { currentReport.ReportData = new (); } + appHandlers = new(); reportGenerationDuration = 0; } @@ -320,12 +316,9 @@ tokenSource = new CancellationTokenSource(); var token = tokenSource.Token; - // clear selected rules - selectedItemsRuleReportTable.Clear(); - selectedItemsChangeReportTable.Clear(); - // save original report for exception case - List managementsReportOrig = currentReport?.ReportData.ManagementData ?? new(); + ReportData reportOrig = currentReport?.ReportData ?? new(); + try { if (actReportFilters.ReportType.IsDeviceRelatedReport() && !actReportFilters.DeviceFilter.isAnyDeviceFilterSet()) @@ -334,10 +327,7 @@ return; } processing = true; - startTime = DateTime.Now; - await PrepareReportGeneration(); - ResetReport(); // reset management data when switching between reports try { @@ -371,18 +361,22 @@ processing = false; PostProcess(); - await InvokeAsync(StateHasChanged); } catch (Exception exception) { processing = false; - currentReport.ReportData.ManagementData = managementsReportOrig; + if(currentReport != null) + { + currentReport.ReportData = reportOrig; + } reportTemplateControl.Uncollapse(); await InvokeAsync(StateHasChanged); DisplayMessageInUi(exception, userConfig.GetText("generate_report"), "", true); } watch.Stop(); reportGenerationDuration = watch.ElapsedMilliseconds/1000.0; + await InvokeAsync(StateHasChanged); + Log.WriteDebug("Report Generation", $"Generation Time: {reportGenerationDuration} s."); } private async Task PrepareReportGeneration() @@ -401,13 +395,20 @@ currentReport = ReportBase.ConstructReport(ConstructReportTemplate(), userConfig); + // clear selected rules + selectedItemsRuleReportTable.Clear(); + selectedItemsChangeReportTable.Clear(); + // save selected managements before resetting relevantManagementIds = actReportFilters.DeviceFilter.getSelectedManagements(); + + // reset report data when switching between reports + ResetReport(); } private async Task GenerateConnectionsReport(CancellationToken token) { - foreach(var selectedOwner in actReportFilters.ModellingFilter.SelectedOwners.Where(o => o.Id > 0)) + foreach(var selectedOwner in actReportFilters.ModellingFilter.SelectedOwners) { OwnerReport actOwnerData = new(){ Name = selectedOwner.Name }; currentReport.ReportData.OwnerData.Add(actOwnerData); @@ -425,11 +426,12 @@ async Task PrepareReportData(FwoOwner selectedOwner, OwnerReport ownerData) { - appHandler = new (apiConnection, userConfig, selectedOwner, DisplayMessageInUi); + ModellingAppHandler appHandler = new (apiConnection, userConfig, selectedOwner, DisplayMessageInUi); await appHandler.Init(ownerData.Connections); ownerData.RegularConnections = appHandler.GetRegularConnections(); ownerData.Interfaces = appHandler.GetInterfaces(); ownerData.CommonServices = appHandler.GetCommonServices(); + appHandlers.Add(appHandler); } private async Task GenerateStatisticsReport(CancellationToken token) @@ -458,7 +460,9 @@ { bool rulesFound = false; foreach (var managementReport in ManagementReports) + { foreach (var device in managementReport.Devices) + { if (device.ContainsRules()) { rulesFound = true; @@ -467,6 +471,8 @@ rule.Metadata.UpdateRecertPeriods(userConfig.RecertificationPeriod, userConfig.RecertificationNoticePeriod); } } + } + } return rulesFound; } @@ -485,9 +491,6 @@ DisplayMessageInUi(null, userConfig.GetText("generate_report"), userConfig.GetText("E4003"), true); } } - - Log.WriteDebug("Report Generation", $"Generation Time: {DateTime.Now - startTime}."); - rsbTabset?.SetActiveTab(1); } private void CancelGeneration() diff --git a/roles/ui/files/FWO.UI/Pages/Reporting/Reports/ConnectionsReport.razor b/roles/ui/files/FWO.UI/Pages/Reporting/Reports/ConnectionsReport.razor index 84582e732..7ea61d938 100644 --- a/roles/ui/files/FWO.UI/Pages/Reporting/Reports/ConnectionsReport.razor +++ b/roles/ui/files/FWO.UI/Pages/Reporting/Reports/ConnectionsReport.razor @@ -5,32 +5,35 @@ @inject UserConfig userConfig -@if(AppHandler != null) +@foreach(var appHandler in AppHandlers) { -
@AppHandler.Application.Display(userConfig.GetText("common_service"))
+
@appHandler.Application.Display(userConfig.GetText("common_service"))
- @if(AppHandler.GetRegularConnections().Count > 0) + @if(appHandler.GetRegularConnections().Count > 0) { - + } - @if(AppHandler.GetInterfaces().Count > 0) + @if(appHandler.GetInterfaces().Count > 0) { - + } - @if(AppHandler.GetCommonServices().Count > 0) + @if(appHandler.GetCommonServices().Count > 0) { - + } +} +@if(AppHandlers.Count > 0) +{ @if(AllCommonServices != null && AllCommonServices.Count > 0) { - + } } @@ -38,7 +41,7 @@ @code { [Parameter] - public ModellingAppHandler? AppHandler { get; set; } = null; + public List AppHandlers { get; set; } = null; [Parameter] public List? AllCommonServices { get; set; } = null; diff --git a/roles/ui/files/FWO.UI/Shared/TabSet.razor b/roles/ui/files/FWO.UI/Shared/TabSet.razor index 1027834a7..95e5ba520 100644 --- a/roles/ui/files/FWO.UI/Shared/TabSet.razor +++ b/roles/ui/files/FWO.UI/Shared/TabSet.razor @@ -48,11 +48,11 @@ internal void AddTab(Tab tab, int pos = -1) { - if (ActiveTab == null) + Tabs.Insert(pos >= 0 && pos <= Tabs.Count ? pos : Tabs.Count, tab); + if (ActiveTab == null || Tabs.Count == 1) { SetActiveTab(tab); } - Tabs.Insert(pos >= 0 && pos <= Tabs.Count ? pos : Tabs.Count, tab); StateHasChanged(); } diff --git a/roles/ui/files/FWO.UI/wwwroot/css/site.css b/roles/ui/files/FWO.UI/wwwroot/css/site.css index 952f1ab6d..eec40722f 100644 --- a/roles/ui/files/FWO.UI/wwwroot/css/site.css +++ b/roles/ui/files/FWO.UI/wwwroot/css/site.css @@ -284,8 +284,8 @@ h5 { height: 100%; width: 4px; background-color: black; - z-index: 20; border-style: double; + cursor: ew-resize; } .sidebar-min-max-button { From 825c369921567e8aea604f8bd90e5399261735a2 Mon Sep 17 00:00:00 2001 From: abarz722 Date: Sun, 24 Mar 2024 15:55:39 +0100 Subject: [PATCH 2/4] improve ip handling --- .../APIcalls/modelling/newAppServer.graphql | 3 +- .../files/FWO.Api.Client/Data/DisplayBase.cs | 134 +++++++++++------- .../FWO.Api.Client/Data/ModellingAppServer.cs | 9 +- .../FWO.Middleware.Server/AppDataImport.cs | 4 +- roles/test/files/FWO.Test/DisplayBaseTest.cs | 68 +++++++++ .../Services/ModellingAppServerHandler.cs | 3 +- 6 files changed, 164 insertions(+), 57 deletions(-) create mode 100644 roles/test/files/FWO.Test/DisplayBaseTest.cs diff --git a/roles/lib/files/FWO.Api.Client/APIcalls/modelling/newAppServer.graphql b/roles/lib/files/FWO.Api.Client/APIcalls/modelling/newAppServer.graphql index bc4eae35a..8a2bf3edf 100644 --- a/roles/lib/files/FWO.Api.Client/APIcalls/modelling/newAppServer.graphql +++ b/roles/lib/files/FWO.Api.Client/APIcalls/modelling/newAppServer.graphql @@ -2,13 +2,14 @@ mutation newAppServer( $name: String $appId: Int $ip: cidr + $ipEnd: cidr $importSource: String ) { insert_owner_network(objects: { name: $name owner_id: $appId ip: $ip - ip_end: $ip + ip_end: $ipEnd import_source: $importSource is_deleted: false nw_type: 10 diff --git a/roles/lib/files/FWO.Api.Client/Data/DisplayBase.cs b/roles/lib/files/FWO.Api.Client/Data/DisplayBase.cs index 17307b5d0..7a1356b0b 100644 --- a/roles/lib/files/FWO.Api.Client/Data/DisplayBase.cs +++ b/roles/lib/files/FWO.Api.Client/Data/DisplayBase.cs @@ -2,7 +2,6 @@ using NetTools; using FWO.Logging; using System.Net; -using System.Text.RegularExpressions; namespace FWO.Api.Data { @@ -10,14 +9,21 @@ public static class DisplayBase { public static StringBuilder DisplayService(NetworkService service, bool isTechReport, string? serviceName = null) { - StringBuilder result = new StringBuilder(); + StringBuilder result = new (); string ports = service.DestinationPortEnd == null || service.DestinationPortEnd == 0 || service.DestinationPort == service.DestinationPortEnd ? $"{service.DestinationPort}" : $"{service.DestinationPort}-{service.DestinationPortEnd}"; if (isTechReport) { if (service.DestinationPort == null) { - result.Append($"{service.Name}"); + if (service.Protocol?.Name != null) + { + result.Append($"{service.Protocol?.Name}"); + } + else + { + result.Append($"{service.Name}"); + } } else { @@ -41,18 +47,21 @@ public static StringBuilder DisplayService(NetworkService service, bool isTechRe public static string DisplayIpWithName(NetworkObject elem) { - string ip = DisplayIp(elem.IP, elem.IpEnd); if(elem.Name != null && elem.Name != "") { - return elem.Name + " (" + ip + ")"; + return elem.Name + DisplayIp(elem.IP, elem.IpEnd, true); } - return ip; + return DisplayIp(elem.IP, elem.IpEnd); } public static string DisplayIp(string ip1, string ip2, bool inBrackets = false) { try { + if (ip2 == "") + { + ip2 = ip1; + } string nwObjType = AutoDetectType(ip1, ip2); return DisplayIp(ip1, ip2, nwObjType, inBrackets); } @@ -66,72 +75,88 @@ public static string DisplayIp(string ip1, string ip2, bool inBrackets = false) public static string DisplayIp(string ip1, string ip2, string nwObjType, bool inBrackets = false) { string result = ""; - IPAddressRange IpRange; - string IpStart; - string IpEnd; if (nwObjType != ObjectType.Group) { - if (ip2 == null) + if (!IsV4Address(ip1) && !IsV6Address(ip1)) + { + Log.WriteError("Ip displaying", $"Found undefined IP family: {ip1} - {ip2}"); + } + else if (IsV4Address(ip1) == IsV6Address(ip2)) { - Log.WriteError("Ip displaying", $"Found undefined IpEnd {ip2}"); + Log.WriteError("Ip displaying", $"Found mixed IP family: {ip1} - {ip2}"); } else { - if (!isV4Address(ip1) && !isV6Address(ip1)) + if (ip2 == "") { - Log.WriteError("Ip displaying", $"Found undefined IP family: {ip1} - {ip2}"); + ip2 = ip1; } - else - { - if (isV4Address(ip1)) - { - IpStart = ip1.Replace("/32", ""); - IpEnd = ip2.Replace("/32", ""); - } - else - { - IpStart = ip1.Replace("/128", ""); - IpEnd = ip2.Replace("/128", ""); - } + string IpStart = StripOffUnnecessaryNetmask(ip1); + string IpEnd = StripOffUnnecessaryNetmask(ip2); - try + try + { + result = inBrackets ? " (" : ""; + if (nwObjType == ObjectType.Network) { - IpRange = new IPAddressRange(IPAddress.Parse(IpStart), IPAddress.Parse(IpEnd)); - if (IpRange != null) + if(GetNetmask(IpStart) == "") { - result = inBrackets ? " (" : ""; - if (nwObjType == ObjectType.Network) - { - result += IpRange.ToCidrString(); - } - else + IPAddressRange ipRange = new (IPAddress.Parse(IpStart), IPAddress.Parse(IpEnd)); + if (ipRange != null) { - result += IpStart; - if (nwObjType.Contains(ObjectType.IPRange)) - { - result += $"-{IpEnd}"; - } + result += ipRange.ToCidrString(); } - result += inBrackets ? ")" : ""; + } + else + { + result += IpStart; } } - catch (Exception exc) + else { - Log.WriteError("Ip displaying", $"Wrong ip format {IpStart} - {IpEnd}\nMessage: {exc.Message}"); + result += IpStart; + if (nwObjType == ObjectType.IPRange) + { + result += $"-{IpEnd}"; + } } + result += inBrackets ? ")" : ""; + } + catch (Exception exc) + { + Log.WriteError("Ip displaying", $"Wrong ip format {IpStart} - {IpEnd}\nMessage: {exc.Message}"); } } } return result; } + public static string GetNetmask(string ip) + { + int pos = ip.LastIndexOf("/"); + if (pos > -1 && ip.Length > pos + 1) + { + return ip[(pos + 1)..]; + } + return ""; + } + private static string StripOffNetmask(string ip) { - Match match = Regex.Match(ip, @"^([\d\.\:]+)\/"); - if (match.Success) + int pos = ip.LastIndexOf("/"); + if (pos > -1 && ip.Length > pos + 1) + { + return ip[..pos]; + } + return ip; + } + + private static string StripOffUnnecessaryNetmask(string ip) + { + string netmask = GetNetmask(ip); + if (IsV4Address(ip) && netmask == "32" || IsV6Address(ip) && netmask == "128") { - string matchedString = match.Value; - return matchedString.Remove( matchedString.Length - 1 ); + return StripOffNetmask(ip); } return ip; } @@ -152,10 +177,17 @@ private static bool SpanSingleNetwork(string ipInStart, string ipInEnd) return true; } - private static string AutoDetectType(string ip1, string ip2) + public static string AutoDetectType(string ip1, string ip2) { + ip1 = StripOffUnnecessaryNetmask(ip1); + ip2 = StripOffUnnecessaryNetmask(ip2); if (ip1 == ip2) { + string netmask = GetNetmask(ip1); + if(netmask != "") + { + return ObjectType.Network; + } return ObjectType.Host; } if (SpanSingleNetwork(ip1, ip2)) @@ -165,14 +197,14 @@ private static string AutoDetectType(string ip1, string ip2) return ObjectType.IPRange; } - private static bool isV6Address(string ip) + private static bool IsV6Address(string ip) { - return ip.Contains(":"); + return ip.Contains(':'); } - private static bool isV4Address(string ip) + private static bool IsV4Address(string ip) { - return ip.Contains("."); + return ip.Contains('.'); } } } diff --git a/roles/lib/files/FWO.Api.Client/Data/ModellingAppServer.cs b/roles/lib/files/FWO.Api.Client/Data/ModellingAppServer.cs index 13e846dd6..5fa878125 100644 --- a/roles/lib/files/FWO.Api.Client/Data/ModellingAppServer.cs +++ b/roles/lib/files/FWO.Api.Client/Data/ModellingAppServer.cs @@ -8,6 +8,9 @@ public class ModellingAppServer : ModellingNwObject [JsonProperty("ip"), JsonPropertyName("ip")] public string Ip { get; set; } = ""; + [JsonProperty("ip_end"), JsonPropertyName("ip_end")] + public string IpEnd { get; set; } = ""; + [JsonProperty("import_source"), JsonPropertyName("import_source")] public string ImportSource { get; set; } = ""; @@ -34,6 +37,7 @@ public override bool Sanitize() { bool shortened = base.Sanitize(); Ip = Sanitizer.SanitizeCidrMand(Ip, ref shortened); + IpEnd = Sanitizer.SanitizeCidrMand(IpEnd, ref shortened); ImportSource = Sanitizer.SanitizeMand(ImportSource, ref shortened); return shortened; } @@ -46,7 +50,7 @@ public static NetworkObject ToNetworkObject(ModellingAppServer appServer) Number = appServer.Number, Name = appServer.Name, IP = appServer.Ip, - IpEnd = appServer.Ip + IpEnd = appServer.IpEnd }; } @@ -61,6 +65,7 @@ public ModellingAppServer(ModellingAppServer appServer) Name = appServer.Name; IsDeleted = appServer.IsDeleted; Ip = appServer.Ip; + IpEnd = appServer.IpEnd; ImportSource = appServer.ImportSource; InUse = appServer.InUse; } @@ -70,7 +75,7 @@ public override bool Equals(object? obj) return obj switch { ModellingAppServer apps => Id == apps.Id && AppId == apps.AppId && Name == apps.Name && IsDeleted == apps.IsDeleted - && Ip == apps.Ip && ImportSource == apps.ImportSource && InUse == apps.InUse, + && Ip == apps.Ip && IpEnd == apps.IpEnd && ImportSource == apps.ImportSource && InUse == apps.InUse, _ => base.Equals(obj), }; } diff --git a/roles/middleware/files/FWO.Middleware.Server/AppDataImport.cs b/roles/middleware/files/FWO.Middleware.Server/AppDataImport.cs index d0cba9cbf..0dbb859b8 100644 --- a/roles/middleware/files/FWO.Middleware.Server/AppDataImport.cs +++ b/roles/middleware/files/FWO.Middleware.Server/AppDataImport.cs @@ -352,8 +352,8 @@ private async Task NewAppServer(ModellingImportAppServer incomingAppServer { name = incomingAppServer.Name, appId = appID, - ip = IpAsCidr(incomingAppServer.Ip), // todo ? - // subnet = incomingAppServer.Subnet, + ip = IpAsCidr(incomingAppServer.Ip), + ipEnd = incomingAppServer.IpEnd != "" ? IpAsCidr(incomingAppServer.IpEnd) : IpAsCidr(incomingAppServer.Ip), importSource = impSource }; await apiConnection.SendQueryAsync(Api.Client.Queries.ModellingQueries.newAppServer, Variables); diff --git a/roles/test/files/FWO.Test/DisplayBaseTest.cs b/roles/test/files/FWO.Test/DisplayBaseTest.cs new file mode 100644 index 000000000..a9509f427 --- /dev/null +++ b/roles/test/files/FWO.Test/DisplayBaseTest.cs @@ -0,0 +1,68 @@ +using NUnit.Framework; +using FWO.Api.Data; + +namespace FWO.Test +{ + [TestFixture] + [Parallelizable] + internal class DisplayBaseTest + { + + static readonly string ip1 = "1.0.0.0"; + static readonly string ip2 = "1.0.0.0/32"; + static readonly string ip3 = "1.0.0.3/32"; + static readonly string ip4 = "1.0.1.3/32"; + static readonly string ip5 = "1.0.0.0/24"; + static readonly string ip6 = "1.0.0.0/31"; + static readonly string ip7 = "1.0.0.2/31"; + + static readonly string ip11 = ":a:"; + static readonly string ip12 = ":a:/128"; + static readonly string ip13 = ":a:/111"; + + static readonly NetworkService serv1 = new(){ Name = "Serv1", DestinationPort = 1000, Protocol = new(){ Name="TCP" }}; + static readonly NetworkService serv2 = new(){ Name = "Serv2", DestinationPort = 1000, DestinationPortEnd = 2000, Protocol = new(){ Name="UDP" }}; + static readonly NetworkService serv3 = new(){ Name = "Serv3", Protocol = new(){ Name="ESP" }}; + + [SetUp] + public void Initialize() + {} + + [Test] + public void TestGetNetmask() + { + Assert.AreEqual("", DisplayBase.GetNetmask(ip1)); + Assert.AreEqual("32", DisplayBase.GetNetmask(ip2)); + Assert.AreEqual("24", DisplayBase.GetNetmask(ip5)); + Assert.AreEqual("", DisplayBase.GetNetmask(ip11)); + Assert.AreEqual("111", DisplayBase.GetNetmask(ip13)); + } + + [Test] + public void TestAutoDetectType() + { + Assert.AreEqual(ObjectType.Host, DisplayBase.AutoDetectType(ip1, ip1)); + Assert.AreEqual(ObjectType.Host, DisplayBase.AutoDetectType(ip1, ip2)); + Assert.AreEqual(ObjectType.Network, DisplayBase.AutoDetectType(ip2, ip3)); + Assert.AreEqual(ObjectType.IPRange, DisplayBase.AutoDetectType(ip2, ip4)); + Assert.AreEqual(ObjectType.Network, DisplayBase.AutoDetectType(ip5, ip5)); + // Assert.AreEqual(ObjectType.Network, DisplayBase.AutoDetectType(ip6, ip7)); // should detect this? + Assert.AreEqual(ObjectType.IPRange, DisplayBase.AutoDetectType(ip6, ip7)); + + Assert.AreEqual(ObjectType.Host, DisplayBase.AutoDetectType(ip11, ip11)); + Assert.AreEqual(ObjectType.Host, DisplayBase.AutoDetectType(ip11, ip12)); + Assert.AreEqual(ObjectType.Network, DisplayBase.AutoDetectType(ip13, ip13)); + } + + [Test] + public void TestDisplayService() + { + Assert.AreEqual("Serv1 (1000/TCP)", DisplayBase.DisplayService(serv1, false).ToString()); + Assert.AreEqual("Serv2 (1000-2000/UDP)", DisplayBase.DisplayService(serv2, false).ToString()); + Assert.AreEqual("Serv3 (ESP)", DisplayBase.DisplayService(serv3, false).ToString()); + Assert.AreEqual("NewName (1000/TCP)", DisplayBase.DisplayService(serv1, false, "NewName").ToString()); + Assert.AreEqual("1000-2000/UDP", DisplayBase.DisplayService(serv2, true).ToString()); + Assert.AreEqual("ESP", DisplayBase.DisplayService(serv3, true).ToString()); + } + } +} diff --git a/roles/ui/files/FWO.UI/Services/ModellingAppServerHandler.cs b/roles/ui/files/FWO.UI/Services/ModellingAppServerHandler.cs index 47aa0d072..2b6fe4e16 100644 --- a/roles/ui/files/FWO.UI/Services/ModellingAppServerHandler.cs +++ b/roles/ui/files/FWO.UI/Services/ModellingAppServerHandler.cs @@ -91,7 +91,8 @@ private async Task AddAppServerToDb() { name = ActAppServer.Name, appId = Application.Id, - ip = IPAddressRange.Parse(ActAppServer.Ip).ToCidrString(), // todo ? + ip = IPAddressRange.Parse(ActAppServer.Ip).ToCidrString(), + ipEnd = ActAppServer.IpEnd != "" ? IPAddressRange.Parse(ActAppServer.IpEnd).ToCidrString() : IPAddressRange.Parse(ActAppServer.Ip).ToCidrString(), importSource = GlobalConst.kManual // todo }; ReturnId[]? returnIds = (await apiConnection.SendQueryAsync(ModellingQueries.newAppServer, Variables)).ReturnIds; From 41794616a38567f2e6d3452e4e20cbb3953a3838 Mon Sep 17 00:00:00 2001 From: abarz722 Date: Mon, 25 Mar 2024 09:07:32 +0100 Subject: [PATCH 3/4] manage common area use --- .../files/sql/idempotent/fworch-texts.sql | 8 ++- .../files/FWO.Config.Api/Data/CommonArea.cs | 32 ++++++++++++ .../NetworkModelling/SearchNwObject.razor | 13 +++-- .../Pages/Settings/SettingsModelling.razor | 51 ++++++++++++++----- roles/ui/files/FWO.UI/Services/DefaultInit.cs | 1 + .../Services/ModellingConnectionHandler.cs | 16 +++--- 6 files changed, 96 insertions(+), 25 deletions(-) create mode 100644 roles/lib/files/FWO.Config.Api/Data/CommonArea.cs diff --git a/roles/database/files/sql/idempotent/fworch-texts.sql b/roles/database/files/sql/idempotent/fworch-texts.sql index c540fe21d..fea67e90d 100644 --- a/roles/database/files/sql/idempotent/fworch-texts.sql +++ b/roles/database/files/sql/idempotent/fworch-texts.sql @@ -1808,6 +1808,10 @@ INSERT INTO txt VALUES ('modelling_settings', 'German', 'Modellierungseinstel INSERT INTO txt VALUES ('modelling_settings', 'English', 'Modelling Settings'); INSERT INTO txt VALUES ('modIconify', 'German', 'Nutzung von Piktogrammen'); INSERT INTO txt VALUES ('modIconify', 'English', 'Prefer use of Icons'); +INSERT INTO txt VALUES ('use_in_src', 'German', 'in Quelle'); +INSERT INTO txt VALUES ('use_in_src', 'English', 'in Source'); +INSERT INTO txt VALUES ('use_in_dst', 'German', 'in Ziel'); +INSERT INTO txt VALUES ('use_in_dst', 'English', 'in Destination'); -- monitoring INSERT INTO txt VALUES ('open_alerts', 'German', 'Offene Alarme'); @@ -4441,9 +4445,11 @@ INSERT INTO txt VALUES ('H5619', 'German', 'Eigentümernamen verwenden: Der INSERT INTO txt VALUES ('H5619', 'English', 'Use Owner Name: The name of the owner is used in the middle part of the naming convention for App Roles.'); INSERT INTO txt VALUES ('H5620', 'German', 'Gemeinsame Netzwerkareas: Vom Administrator vorgegebene Netzwerkareas, welche von allen Verbindungen genutzt werden dürfen. Sie sind in der Bibliothek immer sichtbar und stehen dann nicht mehr in der Liste der auszuwählenden Areas für Common Services. + Die beiden Auswahlfelder "in Quelle" und "in Ziel" legen fest, wo die Netzwerkarea genutzt werden darf. '); INSERT INTO txt VALUES ('H5620', 'English', 'Common Network Areas: Network areas defined by the administrator, which are permitted to be used by all connections. - They are visible in the object library and are not offered in the list of available areas for Common Services. + They are visible in the object library and are not offered in the list of available areas for Common Services. + The flags "in Source" and "in Destination" determine, where the Common Network Area are allowed to be used. '); INSERT INTO txt VALUES ('H5621', 'German', 'Ein Modellierer kann einige persönliche Voreinstellungen für die Darstellung der Modellierung überschreiben. Ausgangswert ist der vom Admin in den Modellierungseinstellungen gesetzte Wert. diff --git a/roles/lib/files/FWO.Config.Api/Data/CommonArea.cs b/roles/lib/files/FWO.Config.Api/Data/CommonArea.cs new file mode 100644 index 000000000..37e7983c0 --- /dev/null +++ b/roles/lib/files/FWO.Config.Api/Data/CommonArea.cs @@ -0,0 +1,32 @@ +using Newtonsoft.Json; +using System.Text.Json.Serialization; +using FWO.Api.Data; + +namespace FWO.Config.Api.Data +{ + public class CommonAreaConfig + { + [JsonProperty("area_id"), JsonPropertyName("area_id")] + public long AreaId { get; set; } = 0; + + [JsonProperty("use_in_src"), JsonPropertyName("use_in_src")] + public bool UseInSrc { get; set; } = true; + + [JsonProperty("use_in_dst"), JsonPropertyName("use_in_dst")] + public bool UseInDst { get; set; } = true; + } + + public class CommonArea + { + public ModellingNwGroupWrapper Area { get; set; } = new(); + + public bool UseInSrc { get; set; } = true; + + public bool UseInDst { get; set; } = true; + + public CommonAreaConfig ToConfigItem() + { + return new(){ AreaId = Area.Content.Id, UseInSrc = UseInSrc, UseInDst = UseInDst}; + } + } +} diff --git a/roles/ui/files/FWO.UI/Pages/NetworkModelling/SearchNwObject.razor b/roles/ui/files/FWO.UI/Pages/NetworkModelling/SearchNwObject.razor index 2f981f125..17c49c102 100644 --- a/roles/ui/files/FWO.UI/Pages/NetworkModelling/SearchNwObject.razor +++ b/roles/ui/files/FWO.UI/Pages/NetworkModelling/SearchNwObject.razor @@ -1,4 +1,5 @@ @using FWO.Config.Api +@using FWO.Config.Api.Data @using System.Text.Json @attribute [Authorize(Roles = $"{Roles.Admin}, {Roles.Auditor}, {Roles.Modeller}")] @@ -33,7 +34,7 @@
- + @((MarkupString)obj.DisplayHtml()) @@ -85,6 +86,9 @@ [Parameter] public Func Refresh { get; set; } = DefaultInit.DoNothingSync; + [Parameter] + public Func Add { get; set; } = DefaultInit.DoNothingSync; + [Parameter] public bool CommonAreaMode { get; set; } = false; @@ -93,7 +97,7 @@ private ModellingTypes.ModObjectType selectedType = ModellingTypes.ModObjectType.NetworkArea; private bool singleType = false; private bool typeSelected = false; - private List nwObjects = new(); + private List remainingNwObjects = new(); private ModellingNwGroup? selectedObject; private bool FirstTry = true; @@ -128,10 +132,10 @@ List allNwObjects = await apiConnection.SendQueryAsync>(FWO.Api.Client.Queries.ModellingQueries.getNwGroupObjects, Variables); if(userConfig.ModCommonAreas != "") { - List commonAreaIds = JsonSerializer.Deserialize>(userConfig.ModCommonAreas) ?? new(); + List commonAreaIds = JsonSerializer.Deserialize>(userConfig.ModCommonAreas)?.ConvertAll(x => x.AreaId) ?? new(); allNwObjects = allNwObjects.Where(o => !commonAreaIds.Contains(o.Id)).ToList(); } - nwObjects = allNwObjects.Where(o => ObjectList.FirstOrDefault(sel => sel.Content.Id == o.Id) == null).ToList(); + remainingNwObjects = allNwObjects.Where(o => ObjectList.FirstOrDefault(sel => sel.Content.Id == o.Id) == null).ToList(); typeSelected = true; } catch (Exception exception) @@ -157,6 +161,7 @@ } ObjectList.Add(new ModellingNwGroupWrapper(){ Content = selectedObject ?? throw new Exception("No Object selected.") }); await ObjectListChanged.InvokeAsync(ObjectList); + Add(selectedObject); Refresh(); Close(); } diff --git a/roles/ui/files/FWO.UI/Pages/Settings/SettingsModelling.razor b/roles/ui/files/FWO.UI/Pages/Settings/SettingsModelling.razor index 016467f77..2296dc7c7 100644 --- a/roles/ui/files/FWO.UI/Pages/Settings/SettingsModelling.razor +++ b/roles/ui/files/FWO.UI/Pages/Settings/SettingsModelling.razor @@ -59,10 +59,22 @@
- +
-
@((MarkupString)context.Content.DisplayHtml())
+
@((MarkupString)context.Area.Content.DisplayHtml())
+
+ +
+ +
+
+
+ +
+ +
+
@@ -163,7 +175,7 @@ else
} - + @code @@ -177,10 +189,10 @@ else private List PathsToDelete = new(); private string actPath = ""; private List allAreas = new(); - private List commonAreaIds = new(); - private List commonAreas = new(); - private List AreasToAdd = new(); - private List AreasToDelete = new(); + private List pureAreaList = new(); + private List commAreaConfigItems = new(); + private List commonAreas = new(); + private List AreasToDelete = new(); private bool predefServices = false; private bool searchArea = false; private ModellingNamingConvention namingConvention = new(); @@ -206,17 +218,24 @@ else { if(configData.ModCommonAreas != "") { - commonAreaIds = JsonSerializer.Deserialize>(configData.ModCommonAreas) ?? new(); + commAreaConfigItems = JsonSerializer.Deserialize>(configData.ModCommonAreas) ?? new(); } commonAreas = new(); - foreach(var areaId in commonAreaIds) + foreach(var areaInfo in commAreaConfigItems) { - ModellingNwGroup? area = allAreas.FirstOrDefault(a => a.Id == areaId); + ModellingNwGroup? area = allAreas.FirstOrDefault(a => a.Id == areaInfo.AreaId); if(area != null) { - commonAreas.Add(new () { Content = area }); + commonAreas.Add(new () { Area = new() {Content = area}, UseInSrc = areaInfo.UseInSrc, UseInDst = areaInfo.UseInDst }); } } + pureAreaList = commonAreas.ConvertAll(x => x.Area); + } + + public bool AddArea(ModellingNwGroup area) + { + commonAreas.Add(new () { Area = new() {Content = area} }); + return true; } private void AddPath() @@ -254,12 +273,16 @@ else } configData.ImportAppDataPath = JsonSerializer.Serialize(appDataPaths); configData.ModNamingConvention = JsonSerializer.Serialize(namingConvention); - commonAreaIds = commonAreas.ConvertAll(x => x.Content.Id); + commAreaConfigItems = commonAreas.ConvertAll(x => x.ToConfigItem()); foreach(var area in AreasToDelete) { - commonAreaIds.Remove(area.Content.Id); + CommonAreaConfig? existingItem = commAreaConfigItems.FirstOrDefault(x => x.AreaId == area.Area.Content.Id); + if (existingItem != null) + { + commAreaConfigItems.Remove(existingItem); + } } - configData.ModCommonAreas = JsonSerializer.Serialize(commonAreaIds); + configData.ModCommonAreas = JsonSerializer.Serialize(commAreaConfigItems); await globalConfig.WriteToDatabase(configData, apiConnection); PathsToDelete = new(); PathsToAdd = new(); diff --git a/roles/ui/files/FWO.UI/Services/DefaultInit.cs b/roles/ui/files/FWO.UI/Services/DefaultInit.cs index 747d066e1..1917c68ef 100644 --- a/roles/ui/files/FWO.UI/Services/DefaultInit.cs +++ b/roles/ui/files/FWO.UI/Services/DefaultInit.cs @@ -14,5 +14,6 @@ public static void DoNothing(Exception? e, string t, string m, bool E) {} public static bool DoNothingSync() { return false; } + public static bool DoNothingSync(ModellingNwGroup _) { return false; } } } diff --git a/roles/ui/files/FWO.UI/Services/ModellingConnectionHandler.cs b/roles/ui/files/FWO.UI/Services/ModellingConnectionHandler.cs index bd8a9e390..e3cbe9d2f 100644 --- a/roles/ui/files/FWO.UI/Services/ModellingConnectionHandler.cs +++ b/roles/ui/files/FWO.UI/Services/ModellingConnectionHandler.cs @@ -1,4 +1,5 @@ using FWO.Config.Api; +using FWO.Config.Api.Data; using FWO.Api.Data; using FWO.Api.Client; using FWO.Api.Client.Queries; @@ -16,6 +17,7 @@ public class ModellingConnectionHandler : ModellingHandlerBase public List AvailableAppRoles { get; set; } = new(); public List AvailableSelectedObjects { get; set; } = new(); public List AvailableCommonAreas { get; set; } = new(); + public List CommonAreaConfigItems { get; set; } = new(); public List> AvailableNwElems { get; set; } = new(); public List AvailableServiceGroups { get; set; } = new(); public List AvailableServices { get; set; } = new(); @@ -111,15 +113,15 @@ public async Task InitAvailableNWObjects() AvailableAppRoles = await apiConnection.SendQueryAsync>(ModellingQueries.getAppRoles, new { appId = Application.Id }); List allAreas = await apiConnection.SendQueryAsync>(ModellingQueries.getNwGroupObjects, new { grpType = (int)ModellingTypes.ModObjectType.NetworkArea }); - List commonAreaIds = new(); + CommonAreaConfigItems = new(); if(userConfig.ModCommonAreas != "") { - commonAreaIds = JsonSerializer.Deserialize>(userConfig.ModCommonAreas) ?? new(); + CommonAreaConfigItems = JsonSerializer.Deserialize>(userConfig.ModCommonAreas) ?? new(); } AvailableCommonAreas = new(); - foreach(var areaId in commonAreaIds) + foreach(var comAreaConfig in CommonAreaConfigItems) { - ModellingNwGroup? area = allAreas.FirstOrDefault(a => a.Id == areaId); + ModellingNwGroup? area = allAreas.FirstOrDefault(a => a.Id == comAreaConfig.AreaId); if(area != null) { AvailableCommonAreas.Add(new () { Content = area }); @@ -349,7 +351,8 @@ public void NwGroupToSource(List nwGroups) { foreach(var nwGroup in nwGroups) { - if(ActConn.SourceNwGroups.FirstOrDefault(w => w.Content.Id == nwGroup.Id) == null && !SrcNwGroupsToAdd.Contains(nwGroup)) + if(ActConn.SourceNwGroups.FirstOrDefault(w => w.Content.Id == nwGroup.Id) == null && !SrcNwGroupsToAdd.Contains(nwGroup) && + (CommonAreaConfigItems.FirstOrDefault(x => x.AreaId == nwGroup.Id)?.UseInSrc ?? true)) { SrcNwGroupsToAdd.Add(nwGroup); } @@ -364,7 +367,8 @@ public void NwGroupToDestination(List nwGroups) { foreach(var nwGroup in nwGroups) { - if(ActConn.DestinationNwGroups.FirstOrDefault(w => w.Content.Id == nwGroup.Id) == null && !DstNwGroupsToAdd.Contains(nwGroup)) + if(ActConn.DestinationNwGroups.FirstOrDefault(w => w.Content.Id == nwGroup.Id) == null && !DstNwGroupsToAdd.Contains(nwGroup) && + (CommonAreaConfigItems.FirstOrDefault(x => x.AreaId == nwGroup.Id)?.UseInDst ?? true)) { DstNwGroupsToAdd.Add(nwGroup); } From fcef842b9262207b933fdb82622435415d3c35e4 Mon Sep 17 00:00:00 2001 From: abarz722 Date: Mon, 25 Mar 2024 10:01:23 +0100 Subject: [PATCH 4/4] layout adjustment --- .../Pages/Settings/SettingsModelling.razor | 30 +++++++++++-------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/roles/ui/files/FWO.UI/Pages/Settings/SettingsModelling.razor b/roles/ui/files/FWO.UI/Pages/Settings/SettingsModelling.razor index 2296dc7c7..6d9cb3c6f 100644 --- a/roles/ui/files/FWO.UI/Pages/Settings/SettingsModelling.razor +++ b/roles/ui/files/FWO.UI/Pages/Settings/SettingsModelling.razor @@ -24,13 +24,13 @@ @onclick="PredefServices">@(userConfig.GetText("predef_services"))
-
+
-
+
@@ -42,13 +42,13 @@
-
+
-
+
@@ -61,18 +61,22 @@
-
+
@((MarkupString)context.Area.Content.DisplayHtml())
- -
- +
+
@(userConfig.GetText("use_in_src")):
+
+ +
- -
- +
+
@(userConfig.GetText("use_in_dst")):
+
+ +
@@ -86,7 +90,7 @@

-
+
@@ -106,7 +110,7 @@
-
+