From d00b96c3418b31356862ea9f6e71a171c8ab0fd4 Mon Sep 17 00:00:00 2001 From: Tudor Stanciu Date: Tue, 18 Apr 2023 02:19:15 +0300 Subject: [PATCH] Display fake sensitive information for guest users. --- ReleaseNotes.xml | 1 + .../DependencyInjectionExtensions.cs | 1 + .../Extensions/ModelExtensions.cs | 25 +++ .../Helpers/DataFaker.cs | 38 +++++ .../Helpers/Randomizer.cs | 130 ++++++++++++++ .../Queries/GetMachines.cs | 14 +- .../Services/Abstractions/IUserService.cs | 9 + .../Services/UserService.cs | 24 +++ .../NetworkResurrector.Api.csproj | 4 +- .../NetworkResurrector.Api/ReleaseNotes.xml | 161 ------------------ 10 files changed, 240 insertions(+), 167 deletions(-) create mode 100644 src/api/NetworkResurrector.Api.Application/Extensions/ModelExtensions.cs create mode 100644 src/api/NetworkResurrector.Api.Application/Helpers/DataFaker.cs create mode 100644 src/api/NetworkResurrector.Api.Application/Helpers/Randomizer.cs create mode 100644 src/api/NetworkResurrector.Api.Application/Services/Abstractions/IUserService.cs create mode 100644 src/api/NetworkResurrector.Api.Application/Services/UserService.cs delete mode 100644 src/api/NetworkResurrector.Api/ReleaseNotes.xml diff --git a/ReleaseNotes.xml b/ReleaseNotes.xml index 1d684ca..9073f99 100644 --- a/ReleaseNotes.xml +++ b/ReleaseNotes.xml @@ -179,6 +179,7 @@ • The "Netmash.Security.Authentication.Tuitio" nuget package has been upgraded in backend. • Added cache and authorization policies. • Added authorization rules based on permissions. + • Display fake sensitive information for guest users. \ No newline at end of file diff --git a/src/api/NetworkResurrector.Api.Application/DependencyInjectionExtensions.cs b/src/api/NetworkResurrector.Api.Application/DependencyInjectionExtensions.cs index dfc82a3..f460a5c 100644 --- a/src/api/NetworkResurrector.Api.Application/DependencyInjectionExtensions.cs +++ b/src/api/NetworkResurrector.Api.Application/DependencyInjectionExtensions.cs @@ -12,6 +12,7 @@ namespace NetworkResurrector.Api.Application services.AddSingleton(); services.AddScoped(); services.Decorate(); + services.AddScoped(); } } } diff --git a/src/api/NetworkResurrector.Api.Application/Extensions/ModelExtensions.cs b/src/api/NetworkResurrector.Api.Application/Extensions/ModelExtensions.cs new file mode 100644 index 0000000..bd3accd --- /dev/null +++ b/src/api/NetworkResurrector.Api.Application/Extensions/ModelExtensions.cs @@ -0,0 +1,25 @@ +using NetworkResurrector.Api.Application.Helpers; +using NetworkResurrector.Api.Application.Queries; +using System; +using System.Linq; + +namespace NetworkResurrector.Api.Application.Extensions +{ + internal static class ModelExtensions + { + public static void Fake(this GetMachines.Model[] models) + { + var count = models.Length; + var ips = DataFaker.GenerateIPv4AddressesInSubnet(count).ToArray(); + + foreach (var model in models) + { + model.MachineName = DataFaker.GenerateName(); + model.FullMachineName = $"{model.MachineName}.DEMO.LAB"; + model.IPv4Address = ips[Array.IndexOf(models, model)]; + model.MACAddress = Randomizer.Randomize(model.MACAddress); + model.Description = $"{model.FullMachineName} description"; + } + } + } +} diff --git a/src/api/NetworkResurrector.Api.Application/Helpers/DataFaker.cs b/src/api/NetworkResurrector.Api.Application/Helpers/DataFaker.cs new file mode 100644 index 0000000..b25b4be --- /dev/null +++ b/src/api/NetworkResurrector.Api.Application/Helpers/DataFaker.cs @@ -0,0 +1,38 @@ +using System; +using System.Collections.Generic; + +namespace NetworkResurrector.Api.Application.Helpers +{ + internal static class DataFaker + { + private static readonly Random Random = new Random(); + private static readonly string[] Names = { "Apollo", "Athena", "Cronus", "Diana", "Hermes", "Jupiter", "Mars", "Mercury", "Neptune", "Saturn", "Uranus", "Venus" }; + private static readonly string[] Codes = { "Node", "Hypervisor", "Srv", "WebSrv", "SqlSrv", "Host", "Agent" }; + + public static string GenerateName() + { + var codeIndex = Random.Next(Codes.Length); + var nameIndex = Random.Next(Names.Length); + return $"{Names[nameIndex]}{Codes[codeIndex]}"; + } + + public static IEnumerable GenerateIPv4AddressesInSubnet(int count) + { + Random random = new Random(); + byte[] subnet = new byte[4]; + random.NextBytes(subnet); + subnet[0] = (byte)((subnet[0] & 0xF0) | 0x0A); // set first octet to 10.x.x.x (private IP range) + + var addresses = new List(); + for (int i = 0; i < count; i++) + { + byte[] ip = new byte[4]; + random.NextBytes(ip); + ip[0] = subnet[0]; + ip[1] = subnet[1]; + addresses.Add(string.Join(".", ip)); + } + return addresses; + } + } +} diff --git a/src/api/NetworkResurrector.Api.Application/Helpers/Randomizer.cs b/src/api/NetworkResurrector.Api.Application/Helpers/Randomizer.cs new file mode 100644 index 0000000..8f2eb84 --- /dev/null +++ b/src/api/NetworkResurrector.Api.Application/Helpers/Randomizer.cs @@ -0,0 +1,130 @@ +using System; +using System.Reflection; + +namespace NetworkResurrector.Api.Application.Helpers +{ + internal static class Randomizer + { + private static readonly Random random = new Random(); + + public static string Randomize(string originalString) + { + var newString = new char[originalString.Length]; + + for (int i = 0; i < originalString.Length; i++) + { + if (char.IsLetter(originalString[i])) + { + if (char.IsUpper(originalString[i])) + { + newString[i] = GetRandomUpperLetter(); + } + else + { + newString[i] = GetRandomLowerLetter(); + } + } + else if (char.IsDigit(originalString[i])) + { + newString[i] = GetRandomDigit(); + } + else + { + newString[i] = originalString[i]; + } + } + + var newStringValue = new string(newString); + return newStringValue; + } + + public static void ReplaceStringProperties(object obj) + { + if (obj == null) return; + + var objectType = obj.GetType(); + var properties = objectType.GetProperties(); + + if (obj is string) + { + var originalString = (string)obj; + var newStringValue = Randomize(originalString); + + if (newStringValue != originalString) + { + objectType.InvokeMember("value", BindingFlags.Instance | BindingFlags.Public | BindingFlags.SetProperty, Type.DefaultBinder, obj, new object[] { newStringValue }); + } + } + else if (obj is Array array) + { + foreach (var item in array) + { + ReplaceStringProperties(item); + } + } + else + { + foreach (var property in properties) + { + if (property.PropertyType == typeof(string)) + { + var originalString = (string)property.GetValue(obj); + var newString = new char[originalString.Length]; + + for (int i = 0; i < originalString.Length; i++) + { + if (char.IsLetter(originalString[i])) + { + if (char.IsUpper(originalString[i])) + { + newString[i] = GetRandomUpperLetter(); + } + else + { + newString[i] = GetRandomLowerLetter(); + } + } + else if (char.IsDigit(originalString[i])) + { + newString[i] = GetRandomDigit(); + } + else + { + newString[i] = originalString[i]; + } + } + + var newStringValue = new string(newString); + + if (newStringValue != originalString) + { + property.SetValue(obj, newStringValue); + } + } + else + { + ReplaceStringProperties(property.GetValue(obj)); + } + } + } + } + + private static char GetRandomUpperLetter() + { + const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + return chars[random.Next(chars.Length)]; + } + + private static char GetRandomLowerLetter() + { + const string chars = "abcdefghijklmnopqrstuvwxyz"; + return chars[random.Next(chars.Length)]; + } + + private static char GetRandomDigit() + { + const string chars = "0123456789"; + return chars[random.Next(chars.Length)]; + } + } +} diff --git a/src/api/NetworkResurrector.Api.Application/Queries/GetMachines.cs b/src/api/NetworkResurrector.Api.Application/Queries/GetMachines.cs index 275e361..3568e5e 100644 --- a/src/api/NetworkResurrector.Api.Application/Queries/GetMachines.cs +++ b/src/api/NetworkResurrector.Api.Application/Queries/GetMachines.cs @@ -1,5 +1,7 @@ using AutoMapper; using MediatR; +using NetworkResurrector.Api.Application.Extensions; +using NetworkResurrector.Api.Application.Services.Abstractions; using NetworkResurrector.Api.Domain.Repositories; using System.Threading; using System.Threading.Tasks; @@ -24,18 +26,24 @@ namespace NetworkResurrector.Api.Application.Queries { private readonly INetworkRepository _repository; private readonly IMapper _mapper; + private readonly IUserService _userService; - public QueryHandler(INetworkRepository repository, IMapper mapper) + public QueryHandler(INetworkRepository repository, IMapper mapper, IUserService userService) { - _repository = repository; - _mapper = mapper; + _repository=repository; + _mapper=mapper; + _userService=userService; } public async Task Handle(Query request, CancellationToken cancellationToken) { + var isGuest = await _userService.GetIsGuest(); var machines = await _repository.GetMachines(); var result = _mapper.Map(machines); + if (isGuest) + result.Fake(); + return result; } } diff --git a/src/api/NetworkResurrector.Api.Application/Services/Abstractions/IUserService.cs b/src/api/NetworkResurrector.Api.Application/Services/Abstractions/IUserService.cs new file mode 100644 index 0000000..ee580d4 --- /dev/null +++ b/src/api/NetworkResurrector.Api.Application/Services/Abstractions/IUserService.cs @@ -0,0 +1,9 @@ +using System.Threading.Tasks; + +namespace NetworkResurrector.Api.Application.Services.Abstractions +{ + public interface IUserService + { + Task GetIsGuest(); + } +} diff --git a/src/api/NetworkResurrector.Api.Application/Services/UserService.cs b/src/api/NetworkResurrector.Api.Application/Services/UserService.cs new file mode 100644 index 0000000..9c35776 --- /dev/null +++ b/src/api/NetworkResurrector.Api.Application/Services/UserService.cs @@ -0,0 +1,24 @@ +using NetworkResurrector.Api.Application.Services.Abstractions; +using NetworkResurrector.Api.Domain.Constants; +using System.Linq; +using System.Threading.Tasks; + +namespace NetworkResurrector.Api.Application.Services +{ + internal class UserService : IUserService + { + private readonly IUserContext _userContext; + + public UserService(IUserContext userContext) + { + _userContext=userContext; + } + + public async Task GetIsGuest() + { + var permissions = await _userContext.GetUserPermissions(); + var isGuest = permissions == null || permissions.Contains(PermissionCodes.GUEST_ACCESS); + return isGuest; + } + } +} diff --git a/src/api/NetworkResurrector.Api/NetworkResurrector.Api.csproj b/src/api/NetworkResurrector.Api/NetworkResurrector.Api.csproj index efa7bd8..4ef6543 100644 --- a/src/api/NetworkResurrector.Api/NetworkResurrector.Api.csproj +++ b/src/api/NetworkResurrector.Api/NetworkResurrector.Api.csproj @@ -6,9 +6,7 @@ - - PreserveNewest - + diff --git a/src/api/NetworkResurrector.Api/ReleaseNotes.xml b/src/api/NetworkResurrector.Api/ReleaseNotes.xml deleted file mode 100644 index 40647a7..0000000 --- a/src/api/NetworkResurrector.Api/ReleaseNotes.xml +++ /dev/null @@ -1,161 +0,0 @@ - - - - 1.0.0 - 2020-11-28 18:15 - - System initialization - Simple .net core 3.1 console application that serve as an REST API through witch a user can execute wake or shutdown commands on machines from his network. - Has been added Wake on LAN support and "wake" route in the API controller. - - - - 1.0.1 - 2020-11-29 22:14 - - New functionalities added - Has been added "ping" and "shutdown" support. Routes with same names have also been added to the controller. - - - - 1.0.2 - 2020-12-20 23:00 - - Changes in the system structure - Replaced Swagger and MediatR implementations with inhouse nuget packages. - Integration with Tuitio. - - - - 1.0.3 - 2022-01-03 08:52 - - Added NetworkResurrector.Agent service - Upgrade all services to net5.0 - NetworkResurrector.Agent is a service that will be installed on a host machine with the scope to execute operations like shutdown, restart, etc directly. - The system will be able to execute these operations in multiple ways. This is just the first one and all of them are handled by the NetworkResurrector.Api. For example, if the user wants to shutdown a clean Windows machine, he can use the agent and configure the API to call it, but in case of a proxmox machine, the API can be configured to execute a http request directly to the OS with the shutdown action (without the need for the agent). - - - - 1.0.4 - 2022-01-14 01:22 - - NetworkResurrector.Agent improvements - • Multiple operations were implemented in the agent: Shutdown, Restart, Sleep, LockLogout and Cancel. The "Cancel" action can cancel one of the previously operations programmed with a delay. - • Added NetworkResurrector.Agent.Wrapper nuget package. It provides an easy and efficient method for a developer to connect another system written in .NET to this agent. - - - - 1.0.5 - 2022-01-18 21:43 - - NetworkResurrector.Server.Wrapper nuget package - • Added NetworkResurrector.Server.Wrapper nuget package. It provides an easy and efficient method for a developer to connect another system written in .NET to NetworkResurrector.Server. - • Added logic where the http headers from the caller's request are automatically passed to the request sent to this server. - - - - 1.0.6 - 2022-06-19 08:18 - - Implemented Netmash.Infrastructure.DatabaseMigration - • Through this nuget package, support was added for the automatic running of new sql scripts at system startup. - • The current sql scripts have been corrected or updated to meet the migrator rules. - - - - 1.0.7 - 2022-11-30 23:21 - - Code cleanup and refactoring - • Preparing to make the project open source on my Gitea instance. - • Removed secrets from source code and from git history - • Exposing two new methods "/ping" and "/version" in a new controller "/system". - - - - 1.1.0 - 2023-01-29 00:31 - - Massive improvements - • .NET 6 upgrade - • Nuget packages upgrade - • Added Seq logging - • Added messaging and published notifications from command handlers - • Refactoring and code cleanup - • Added README.md file - - - - 1.1.1 - 2023-02-02 19:03 - - Retouches after the last upgrade - • Nuget packages upgrade - • Small fixes - - - - 1.1.2 - 2023-02-04 11:14 - - Tuitio latest updates - • Tuitio nuget packages upgrade - • Tuitio configuration changes - • Many frontend developments - • Tuitio client NPM package integration: @flare/tuitio-react-client - • Added license file - • Login with enter key - - - - 1.1.3 - 2023-03-18 02:49 - - Tuitio latest changes - • Account logout method and the latest changes published by Tuitio were implemented - • Netmash.Security.Authentication.Tuitio nuget package upgrade - - - - 1.2.0 - 2023-03-19 14:56 - - Massive frontend developments - • Complete UI refactoring - • A complete menu has been added to the application. - • The theme and the switch between dark and light mode have been implemented. - • Axios upgrade. - • The ugly and useless stepper has been removed from the machines page. - - - - 1.2.1 - 2023-03-19 20:11 - - Frontend developments - • Added sensitive info toggle. - • Apply mask on sensitive information. - • Mask machine logs. - - - - 1.2.2 - 2023-03-19 23:14 - - Added user profile page - • The data on the page is extracted from the Tuitio token. - - - - 1.2.3 - 2023-03-25 02:26 - - Important developments in frontend - • Machines view modes - • New menu entries: About, Administration and System - • About page. It contains information about the system and the release notes. - • New methods have been added to the API for reading the system version and release notes. - - - \ No newline at end of file