Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Server-side remote control session recording. #678

Merged
merged 3 commits into from
Jul 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions Server/API/LoginController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public class LoginController : ControllerBase
private readonly IApplicationConfig _appConfig;
private readonly IDataService _dataService;
private readonly IHubContext<DesktopHub> _desktopHub;
private readonly IDesktopHubSessionCache _desktopSessionCache;
private readonly IRemoteControlSessionCache _remoteControlSessionCache;
private readonly SignInManager<RemotelyUser> _signInManager;
private readonly IHubContext<ViewerHub> _viewerHub;
private readonly ILogger<LoginController> _logger;
Expand All @@ -33,15 +33,15 @@ public LoginController(
IDataService dataService,
IApplicationConfig appConfig,
IHubContext<DesktopHub> casterHubContext,
IDesktopHubSessionCache desktopSessionCache,
IRemoteControlSessionCache remoteControlSessionCache,
IHubContext<ViewerHub> viewerHubContext,
ILogger<LoginController> logger)
{
_signInManager = signInManager;
_dataService = dataService;
_appConfig = appConfig;
_desktopHub = casterHubContext;
_desktopSessionCache = desktopSessionCache;
_remoteControlSessionCache = remoteControlSessionCache;
_viewerHub = viewerHubContext;
_logger = logger;
}
Expand All @@ -54,7 +54,7 @@ public async Task<IActionResult> Logout()
if (HttpContext?.User?.Identity?.IsAuthenticated == true)
{
orgId = _dataService.GetUserByNameWithOrg(HttpContext.User.Identity.Name)?.OrganizationID;
var activeSessions = _desktopSessionCache
var activeSessions = _remoteControlSessionCache
.Sessions
.Where(x => x.RequesterUserName == HttpContext.User.Identity.Name);

Expand Down
10 changes: 5 additions & 5 deletions Server/API/RemoteControlController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ namespace Remotely.Server.API
public class RemoteControlController : ControllerBase
{
private readonly IHubContext<AgentHub> _serviceHub;
private readonly IDesktopHubSessionCache _desktopSessionCache;
private readonly IRemoteControlSessionCache _remoteControlSessionCache;
private readonly IAgentHubSessionCache _serviceSessionCache;
private readonly IApplicationConfig _appConfig;
private readonly IOtpProvider _otpProvider;
Expand All @@ -39,7 +39,7 @@ public class RemoteControlController : ControllerBase
public RemoteControlController(
SignInManager<RemotelyUser> signInManager,
IDataService dataService,
IDesktopHubSessionCache desktopSessionCache,
IRemoteControlSessionCache remoteControlSessionCache,
IHubContext<AgentHub> serviceHub,
IAgentHubSessionCache serviceSessionCache,
IOtpProvider otpProvider,
Expand All @@ -49,7 +49,7 @@ public RemoteControlController(
{
_dataService = dataService;
_serviceHub = serviceHub;
_desktopSessionCache = desktopSessionCache;
_remoteControlSessionCache = remoteControlSessionCache;
_serviceSessionCache = serviceSessionCache;
_appConfig = appConfig;
_otpProvider = otpProvider;
Expand Down Expand Up @@ -117,7 +117,7 @@ private async Task<IActionResult> InitiateRemoteControl(string deviceID, string
}


var sessionCount = _desktopSessionCache.Sessions
var sessionCount = _remoteControlSessionCache.Sessions
.OfType<RemoteControlSessionEx>()
.Count(x => x.OrganizationId == orgID);

Expand All @@ -138,7 +138,7 @@ private async Task<IActionResult> InitiateRemoteControl(string deviceID, string
OrganizationId = orgID
};

_desktopSessionCache.AddOrUpdate($"{sessionId}", session, (k, v) =>
_remoteControlSessionCache.AddOrUpdate($"{sessionId}", session, (k, v) =>
{
if (v is RemoteControlSessionEx ex)
{
Expand Down
4 changes: 2 additions & 2 deletions Server/Areas/Identity/Pages/Account/Logout.cshtml
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@
@inject SignInManager<RemotelyUser> SignInManager
@inject IHubContext<DesktopHub> DesktopHubContext
@inject IHubContext<ViewerHub> ViewerHubContext
@inject IDesktopHubSessionCache DesktopSessionCache
@inject IRemoteControlSessionCache RemoteControlSessionCache

@functions {
public async Task<IActionResult> OnPost()
{
if (SignInManager.IsSignedIn(User))
{
var activeSessions = DesktopSessionCache.Sessions.Where(x => x.RequesterUserName == HttpContext.User.Identity.Name);
var activeSessions = RemoteControlSessionCache.Sessions.Where(x => x.RequesterUserName == HttpContext.User.Identity.Name);
foreach (var session in activeSessions)
{
await DesktopHubContext.Clients.Client(session.DesktopConnectionId).SendAsync("Disconnect", "User logged out.");
Expand Down
10 changes: 5 additions & 5 deletions Server/Hubs/CircuitConnection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ public class CircuitConnection : CircuitHandler, ICircuitConnection
private readonly IAuthService _authService;
private readonly ICircuitManager _circuitManager;
private readonly IDataService _dataService;
private readonly IDesktopHubSessionCache _desktopSessionCache;
private readonly IRemoteControlSessionCache _remoteControlSessionCache;
private readonly ConcurrentQueue<CircuitEvent> _eventQueue = new();
private readonly IExpiringTokenService _expiringTokenService;
private readonly ILogger<CircuitConnection> _logger;
Expand All @@ -94,7 +94,7 @@ public CircuitConnection(
ICircuitManager circuitManager,
IToastService toastService,
IExpiringTokenService expiringTokenService,
IDesktopHubSessionCache desktopSessionCache,
IRemoteControlSessionCache remoteControlSessionCache,
IAgentHubSessionCache agentSessionCache,
ILogger<CircuitConnection> logger)
{
Expand All @@ -106,7 +106,7 @@ public CircuitConnection(
_circuitManager = circuitManager;
_toastService = toastService;
_expiringTokenService = expiringTokenService;
_desktopSessionCache = desktopSessionCache;
_remoteControlSessionCache = remoteControlSessionCache;
_agentSessionCache = agentSessionCache;
_logger = logger;
}
Expand Down Expand Up @@ -244,7 +244,7 @@ public async Task<Result<RemoteControlSessionEx>> RemoteControl(string deviceId,

}

var sessionCount = _desktopSessionCache.Sessions
var sessionCount = _remoteControlSessionCache.Sessions
.OfType<RemoteControlSessionEx>()
.Count(x => x.OrganizationId == User.OrganizationID);

Expand Down Expand Up @@ -281,7 +281,7 @@ public async Task<Result<RemoteControlSessionEx>> RemoteControl(string deviceId,
NotifyUserOnStart = _appConfig.RemoteControlNotifyUser
};

_desktopSessionCache.AddOrUpdate($"{sessionId}", session);
_remoteControlSessionCache.AddOrUpdate($"{sessionId}", session);

var organization = _dataService.GetOrganizationNameByUserName(User.UserName);
await _agentHubContext.Clients.Client(serviceConnectionId).SendAsync("RemoteControl",
Expand Down
7 changes: 7 additions & 0 deletions Server/Pages/ServerConfig.razor
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,13 @@
<br />
<ValidationMessage For="() => Input.DBProvider" />
</div>
<div class="form-group">
<label>Enable Remote Control Recording</label>
<br />
colinblaise marked this conversation as resolved.
Show resolved Hide resolved
<InputCheckbox @bind-Value="Input.EnableRemoteControlRecording" autocomplete="off" />
<br />
<ValidationMessage For="() => Input.EnableRemoteControlRecording" />
</div>
<div class="form-group">
<label>Enable Windows Event Log</label>
<br />
Expand Down
2 changes: 2 additions & 0 deletions Server/Pages/ServerConfig.razor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ public class AppSettingsModel
[JsonConverter(typeof(JsonStringEnumConverter))]
public DbProvider DBProvider { get; set; }

[Display(Name = "Enable Remote Control Recording")]
public bool EnableRemoteControlRecording { get; set; }

[Display(Name = "Enable Windows Event Log")]
public bool EnableWindowsEventLog { get; set; }
Expand Down
4 changes: 3 additions & 1 deletion Server/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,8 @@
config.AddHubEventHandler<HubEventHandler>();
config.AddViewerAuthorizer<ViewerAuthorizer>();
config.AddViewerPageDataProvider<ViewerPageDataProvider>();
config.AddViewerOptionsProvider<ViewerOptionsProvider>();
config.AddSessionRecordingSink<SessionRecordingSink>();
colinblaise marked this conversation as resolved.
Show resolved Hide resolved
});

services.AddSingleton<IAgentHubSessionCache, AgentHubSessionCache>();
Expand Down Expand Up @@ -292,7 +294,7 @@
}

await dataService.SetAllDevicesNotOnline();
dataService.CleanupOldRecords();
await dataService.CleanupOldRecords();
}

await app.RunAsync();
Expand Down
65 changes: 34 additions & 31 deletions Server/Services/ApplicationConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ public interface IApplicationConfig
string[] BannedDevices { get; }
double DataRetentionInDays { get; }
string DBProvider { get; }
bool EnableRemoteControlRecording { get; }
bool EnableWindowsEventLog { get; }
bool EnforceAttendedAccess { get; }
bool ForceClientHttps { get; }
Expand Down Expand Up @@ -40,40 +41,42 @@ public interface IApplicationConfig

public class ApplicationConfig : IApplicationConfig
{
private readonly IConfiguration _config;

public ApplicationConfig(IConfiguration config)
{
Config = config;
_config = config;
}

public bool AllowApiLogin => bool.Parse(Config["ApplicationOptions:AllowApiLogin"] ?? "false");
public string[] BannedDevices => Config.GetSection("ApplicationOptions:BannedDevices").Get<string[]>() ?? System.Array.Empty<string>();
public double DataRetentionInDays => double.Parse(Config["ApplicationOptions:DataRetentionInDays"] ?? "30");
public string DBProvider => Config["ApplicationOptions:DBProvider"] ?? "SQLite";
public bool EnableWindowsEventLog => bool.Parse(Config["ApplicationOptions:EnableWindowsEventLog"]);
public bool EnforceAttendedAccess => bool.Parse(Config["ApplicationOptions:EnforceAttendedAccess"] ?? "false");
public bool ForceClientHttps => bool.Parse(Config["ApplicationOptions:ForceClientHttps"] ?? "false");
public string[] KnownProxies => Config.GetSection("ApplicationOptions:KnownProxies").Get<string[]>() ?? System.Array.Empty<string>();
public int MaxConcurrentUpdates => int.Parse(Config["ApplicationOptions:MaxConcurrentUpdates"] ?? "10");
public int MaxOrganizationCount => int.Parse(Config["ApplicationOptions:MaxOrganizationCount"] ?? "1");
public string MessageOfTheDay => Config["ApplicationOptions:MessageOfTheDay"];
public bool RedirectToHttps => bool.Parse(Config["ApplicationOptions:RedirectToHttps"] ?? "true");
public bool RemoteControlNotifyUser => bool.Parse(Config["ApplicationOptions:RemoteControlNotifyUser"] ?? "true");
public bool RemoteControlRequiresAuthentication => bool.Parse(Config["ApplicationOptions:RemoteControlRequiresAuthentication"] ?? "true");
public int RemoteControlSessionLimit => int.Parse(Config["ApplicationOptions:RemoteControlSessionLimit"] ?? "3");
public bool Require2FA => bool.Parse(Config["ApplicationOptions:Require2FA"] ?? "false");
public string ServerUrl => Config["ApplicationOptions:ServerUrl"];
public bool SmtpCheckCertificateRevocation => bool.Parse(Config["ApplicationOptions:SmtpCheckCertificateRevocation"] ?? "true");
public string SmtpDisplayName => Config["ApplicationOptions:SmtpDisplayName"];
public string SmtpEmail => Config["ApplicationOptions:SmtpEmail"];
public string SmtpHost => Config["ApplicationOptions:SmtpHost"];
public string SmtpLocalDomain => Config["ApplicationOptions:SmtpLocalDomain"];
public string SmtpPassword => Config["ApplicationOptions:SmtpPassword"];
public int SmtpPort => int.Parse(Config["ApplicationOptions:SmtpPort"] ?? "25");
public string SmtpUserName => Config["ApplicationOptions:SmtpUserName"];
public Theme Theme => Enum.Parse<Theme>(Config["ApplicationOptions:Theme"] ?? "Dark", true);
public string[] TrustedCorsOrigins => Config.GetSection("ApplicationOptions:TrustedCorsOrigins").Get<string[]>() ?? System.Array.Empty<string>();
public bool UseHsts => bool.Parse(Config["ApplicationOptions:UseHsts"] ?? "false");
public bool UseHttpLogging => bool.Parse(Config["ApplicationOptions:UseHttpLogging"] ?? "false");
private IConfiguration Config { get; set; }
public bool AllowApiLogin => bool.TryParse(_config["ApplicationOptions:AllowApiLogin"], out var result) && result;
public string[] BannedDevices => _config.GetSection("ApplicationOptions:BannedDevices").Get<string[]>() ?? System.Array.Empty<string>();
public double DataRetentionInDays => double.TryParse(_config["ApplicationOptions:DataRetentionInDays"], out var result) ? result : 30;
public string DBProvider => _config["ApplicationOptions:DBProvider"] ?? "SQLite";
public bool EnableRemoteControlRecording => bool.TryParse(_config["ApplicationOptions:EnableRemoteControlRecording"], out var result) && result;
public bool EnableWindowsEventLog => bool.TryParse(_config["ApplicationOptions:EnableWindowsEventLog"], out var result) && result;
public bool EnforceAttendedAccess => bool.TryParse(_config["ApplicationOptions:EnforceAttendedAccess"], out var result) && result;
public bool ForceClientHttps => bool.TryParse(_config["ApplicationOptions:ForceClientHttps"], out var result) && result;
public string[] KnownProxies => _config.GetSection("ApplicationOptions:KnownProxies").Get<string[]>() ?? System.Array.Empty<string>();
public int MaxConcurrentUpdates => int.TryParse(_config["ApplicationOptions:MaxConcurrentUpdates"], out var result) ? result : 10;
public int MaxOrganizationCount => int.TryParse(_config["ApplicationOptions:MaxOrganizationCount"], out var result) ? result : 1;
public string MessageOfTheDay => _config["ApplicationOptions:MessageOfTheDay"];
public bool RedirectToHttps => bool.TryParse(_config["ApplicationOptions:RedirectToHttps"], out var result) && result;
public bool RemoteControlNotifyUser => bool.TryParse(_config["ApplicationOptions:RemoteControlNotifyUser"], out var result) && result;
public bool RemoteControlRequiresAuthentication => bool.TryParse(_config["ApplicationOptions:RemoteControlRequiresAuthentication"], out var result) && result;
public int RemoteControlSessionLimit => int.TryParse(_config["ApplicationOptions:RemoteControlSessionLimit"], out var result) ? result : 3;
public bool Require2FA => bool.TryParse(_config["ApplicationOptions:Require2FA"], out var result) && result;
public string ServerUrl => _config["ApplicationOptions:ServerUrl"];
public bool SmtpCheckCertificateRevocation => !bool.TryParse(_config["ApplicationOptions:SmtpCheckCertificateRevocation"], out var result) || result;
public string SmtpDisplayName => _config["ApplicationOptions:SmtpDisplayName"];
public string SmtpEmail => _config["ApplicationOptions:SmtpEmail"];
public string SmtpHost => _config["ApplicationOptions:SmtpHost"];
public string SmtpLocalDomain => _config["ApplicationOptions:SmtpLocalDomain"];
public string SmtpPassword => _config["ApplicationOptions:SmtpPassword"];
public int SmtpPort => int.TryParse(_config["ApplicationOptions:SmtpPort"], out var result) ? result : 25;
public string SmtpUserName => _config["ApplicationOptions:SmtpUserName"];
public Theme Theme => Enum.TryParse<Theme>(_config["ApplicationOptions:Theme"], out var result) ? result : Theme.Dark;
public string[] TrustedCorsOrigins => _config.GetSection("ApplicationOptions:TrustedCorsOrigins").Get<string[]>() ?? System.Array.Empty<string>();
public bool UseHsts => bool.TryParse(_config["ApplicationOptions:UseHsts"], out var result) && result;
public bool UseHttpLogging => bool.TryParse(_config["ApplicationOptions:UseHttpLogging"], out var result) && result;
}
}
Loading