SEBWIN-301: Finished basic backup mechanism for service.

This commit is contained in:
dbuechel 2019-06-26 10:13:11 +02:00
parent b96bbfcd78
commit dd801245d2
30 changed files with 552 additions and 167 deletions

View file

@ -16,8 +16,7 @@ namespace SafeExamBrowser.Configuration.ConfigurationData
{ {
internal class DataValues internal class DataValues
{ {
private const string BASE_ADDRESS = "net.pipe://localhost/safeexambrowser"; private const string DEFAULT_CONFIGURATION_NAME = "SebClientSettings.seb";
private const string DEFAULT_FILE_NAME = "SebClientSettings.seb";
private AppConfig appConfig; private AppConfig appConfig;
private string executablePath; private string executablePath;
@ -48,26 +47,26 @@ namespace SafeExamBrowser.Configuration.ConfigurationData
var logFilePrefix = startTime.ToString("yyyy-MM-dd\\_HH\\hmm\\mss\\s"); var logFilePrefix = startTime.ToString("yyyy-MM-dd\\_HH\\hmm\\mss\\s");
appConfig = new AppConfig(); appConfig = new AppConfig();
appConfig.AppDataFilePath = Path.Combine(appDataRoamingFolder, DEFAULT_FILE_NAME); appConfig.AppDataFilePath = Path.Combine(appDataRoamingFolder, DEFAULT_CONFIGURATION_NAME);
appConfig.ApplicationStartTime = startTime; appConfig.ApplicationStartTime = startTime;
appConfig.BrowserCachePath = Path.Combine(appDataLocalFolder, "Cache"); appConfig.BrowserCachePath = Path.Combine(appDataLocalFolder, "Cache");
appConfig.BrowserLogFilePath = Path.Combine(logFolder, $"{logFilePrefix}_Browser.log"); appConfig.BrowserLogFilePath = Path.Combine(logFolder, $"{logFilePrefix}_Browser.log");
appConfig.ClientId = Guid.NewGuid(); appConfig.ClientId = Guid.NewGuid();
appConfig.ClientAddress = $"{BASE_ADDRESS}/client/{Guid.NewGuid()}"; appConfig.ClientAddress = $"{AppConfig.BASE_ADDRESS}/client/{Guid.NewGuid()}";
appConfig.ClientExecutablePath = Path.Combine(Path.GetDirectoryName(executablePath), $"{nameof(SafeExamBrowser)}.Client.exe"); appConfig.ClientExecutablePath = Path.Combine(Path.GetDirectoryName(executablePath), $"{nameof(SafeExamBrowser)}.Client.exe");
appConfig.ClientLogFilePath = Path.Combine(logFolder, $"{logFilePrefix}_Client.log"); appConfig.ClientLogFilePath = Path.Combine(logFolder, $"{logFilePrefix}_Client.log");
appConfig.ConfigurationFileExtension = ".seb"; appConfig.ConfigurationFileExtension = ".seb";
appConfig.DownloadDirectory = Path.Combine(appDataLocalFolder, "Downloads"); appConfig.DownloadDirectory = Path.Combine(appDataLocalFolder, "Downloads");
appConfig.ProgramCopyright = programCopyright; appConfig.ProgramCopyright = programCopyright;
appConfig.ProgramDataFilePath = Path.Combine(programDataFolder, DEFAULT_FILE_NAME); appConfig.ProgramDataFilePath = Path.Combine(programDataFolder, DEFAULT_CONFIGURATION_NAME);
appConfig.ProgramTitle = programTitle; appConfig.ProgramTitle = programTitle;
appConfig.ProgramVersion = programVersion; appConfig.ProgramVersion = programVersion;
appConfig.RuntimeId = Guid.NewGuid(); appConfig.RuntimeId = Guid.NewGuid();
appConfig.RuntimeAddress = $"{BASE_ADDRESS}/runtime/{Guid.NewGuid()}"; appConfig.RuntimeAddress = $"{AppConfig.BASE_ADDRESS}/runtime/{Guid.NewGuid()}";
appConfig.RuntimeLogFilePath = Path.Combine(logFolder, $"{logFilePrefix}_Runtime.log"); appConfig.RuntimeLogFilePath = Path.Combine(logFolder, $"{logFilePrefix}_Runtime.log");
appConfig.SebUriScheme = "seb"; appConfig.SebUriScheme = "seb";
appConfig.SebUriSchemeSecure = "sebs"; appConfig.SebUriSchemeSecure = "sebs";
appConfig.ServiceAddress = $"{BASE_ADDRESS}/service"; appConfig.ServiceAddress = $"{AppConfig.BASE_ADDRESS}/service";
appConfig.ServiceEventName = $@"Global\{nameof(SafeExamBrowser)}-{Guid.NewGuid()}"; appConfig.ServiceEventName = $@"Global\{nameof(SafeExamBrowser)}-{Guid.NewGuid()}";
appConfig.ServiceLogFilePath = Path.Combine(logFolder, $"{logFilePrefix}_Service.log"); appConfig.ServiceLogFilePath = Path.Combine(logFolder, $"{logFilePrefix}_Service.log");
@ -79,7 +78,7 @@ namespace SafeExamBrowser.Configuration.ConfigurationData
var configuration = new SessionConfiguration(); var configuration = new SessionConfiguration();
appConfig.ClientId = Guid.NewGuid(); appConfig.ClientId = Guid.NewGuid();
appConfig.ClientAddress = $"{BASE_ADDRESS}/client/{Guid.NewGuid()}"; appConfig.ClientAddress = $"{AppConfig.BASE_ADDRESS}/client/{Guid.NewGuid()}";
appConfig.ServiceEventName = $@"Global\{nameof(SafeExamBrowser)}-{Guid.NewGuid()}"; appConfig.ServiceEventName = $@"Global\{nameof(SafeExamBrowser)}-{Guid.NewGuid()}";
configuration.AppConfig = appConfig.Clone(); configuration.AppConfig = appConfig.Clone();

View file

@ -16,6 +16,21 @@ namespace SafeExamBrowser.Contracts.Configuration
[Serializable] [Serializable]
public class AppConfig public class AppConfig
{ {
/// <summary>
/// The name of the backup data file used by the service component.
/// </summary>
public const string BACKUP_FILE_NAME = "Backup.bin";
/// <summary>
/// The base address for all communication hosts of the application.
/// </summary>
public const string BASE_ADDRESS = "net.pipe://localhost/safeexambrowser";
/// <summary>
/// The communication address of the service component.
/// </summary>
public const string SERVICE_ADDRESS = BASE_ADDRESS + "/service";
/// <summary> /// <summary>
/// The file path of the local client configuration for the active user. /// The file path of the local client configuration for the active user.
/// </summary> /// </summary>

View file

@ -0,0 +1,26 @@
/*
* Copyright (c) 2019 ETH Zürich, Educational Development and Technology (LET)
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
namespace SafeExamBrowser.Contracts.Lockdown
{
/// <summary>
/// Defines a mechanism which tries to restore all changes saved in a <see cref="IFeatureConfigurationBackup"/>.
/// </summary>
public interface IAutoRestoreMechanism
{
/// <summary>
/// Starts the procedure.
/// </summary>
void Start();
/// <summary>
/// Stops the procedure.
/// </summary>
void Stop();
}
}

View file

@ -6,6 +6,8 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. * file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/ */
using System;
namespace SafeExamBrowser.Contracts.Lockdown namespace SafeExamBrowser.Contracts.Lockdown
{ {
/// <summary> /// <summary>
@ -13,6 +15,16 @@ namespace SafeExamBrowser.Contracts.Lockdown
/// </summary> /// </summary>
public interface IFeatureConfiguration public interface IFeatureConfiguration
{ {
/// <summary>
/// The unique identifier of this feature configuration.
/// </summary>
Guid Id { get; }
/// <summary>
/// The identifier of the group of changes to which this feature configuration belongs.
/// </summary>
Guid GroupId { get; }
/// <summary> /// <summary>
/// Disables the feature. /// Disables the feature.
/// </summary> /// </summary>
@ -29,7 +41,7 @@ namespace SafeExamBrowser.Contracts.Lockdown
void Monitor(); void Monitor();
/// <summary> /// <summary>
/// Restores the feature to its initial configuration. /// Restores the feature to its previous configuration (i.e. before it was enabled or disabled).
/// </summary> /// </summary>
void Restore(); void Restore();
} }

View file

@ -6,6 +6,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. * file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/ */
using System;
using System.Collections.Generic; using System.Collections.Generic;
namespace SafeExamBrowser.Contracts.Lockdown namespace SafeExamBrowser.Contracts.Lockdown
@ -15,19 +16,24 @@ namespace SafeExamBrowser.Contracts.Lockdown
/// </summary> /// </summary>
public interface IFeatureConfigurationBackup public interface IFeatureConfigurationBackup
{ {
/// <summary>
/// Deletes the given <see cref="IFeatureConfiguration"/> from the backup repository.
/// </summary>
void Delete(IFeatureConfiguration configuration);
/// <summary> /// <summary>
/// Gets all <see cref="IFeatureConfiguration"/> currently saved in the backup repository. /// Gets all <see cref="IFeatureConfiguration"/> currently saved in the backup repository.
/// </summary> /// </summary>
IList<IFeatureConfiguration> GetConfigurations(); IList<IFeatureConfiguration> GetAllConfigurations();
/// <summary>
/// Gets all <see cref="IFeatureConfiguration"/> which are part of the given group.
/// </summary>
IList<IFeatureConfiguration> GetBy(Guid groupId);
/// <summary> /// <summary>
/// Saves the given <see cref="IFeatureConfiguration"/> in the backup repository. /// Saves the given <see cref="IFeatureConfiguration"/> in the backup repository.
/// </summary> /// </summary>
void Save(IFeatureConfiguration configuration); void Save(IFeatureConfiguration configuration);
/// <summary>
/// Deletes the given <see cref="IFeatureConfiguration"/> from the backup repository.
/// </summary>
void Delete(IFeatureConfiguration configuration);
} }
} }

View file

@ -6,6 +6,8 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. * file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/ */
using System;
namespace SafeExamBrowser.Contracts.Lockdown namespace SafeExamBrowser.Contracts.Lockdown
{ {
/// <summary> /// <summary>
@ -16,61 +18,61 @@ namespace SafeExamBrowser.Contracts.Lockdown
/// <summary> /// <summary>
/// Creates an <see cref="IFeatureConfiguration"/> to control notifications of the Google Chrome browser. /// Creates an <see cref="IFeatureConfiguration"/> to control notifications of the Google Chrome browser.
/// </summary> /// </summary>
IFeatureConfiguration CreateChromeNotificationConfiguration(); IFeatureConfiguration CreateChromeNotificationConfiguration(Guid groupId);
/// <summary> /// <summary>
/// Creates an <see cref="IFeatureConfiguration"/> to control the ease of access options on the security screen. /// Creates an <see cref="IFeatureConfiguration"/> to control the ease of access options on the security screen.
/// </summary> /// </summary>
IFeatureConfiguration CreateEaseOfAccessConfiguration(); IFeatureConfiguration CreateEaseOfAccessConfiguration(Guid groupId);
/// <summary> /// <summary>
/// Creates an <see cref="IFeatureConfiguration"/> to control the network options on the security screen. /// Creates an <see cref="IFeatureConfiguration"/> to control the network options on the security screen.
/// </summary> /// </summary>
IFeatureConfiguration CreateNetworkOptionsConfiguration(); IFeatureConfiguration CreateNetworkOptionsConfiguration(Guid groupId);
/// <summary> /// <summary>
/// Creates an <see cref="IFeatureConfiguration"/> to control the option to change the password of a user account via the security screen. /// Creates an <see cref="IFeatureConfiguration"/> to control the option to change the password of a user account via the security screen.
/// </summary> /// </summary>
IFeatureConfiguration CreatePasswordChangeConfiguration(); IFeatureConfiguration CreatePasswordChangeConfiguration(Guid groupId);
/// <summary> /// <summary>
/// Creates an <see cref="IFeatureConfiguration"/> to control the power options on the security screen. /// Creates an <see cref="IFeatureConfiguration"/> to control the power options on the security screen.
/// </summary> /// </summary>
IFeatureConfiguration CreatePowerOptionsConfiguration(); IFeatureConfiguration CreatePowerOptionsConfiguration(Guid groupId);
/// <summary> /// <summary>
/// Creates an <see cref="IFeatureConfiguration"/> to control remote desktop connections. /// Creates an <see cref="IFeatureConfiguration"/> to control remote desktop connections.
/// </summary> /// </summary>
IFeatureConfiguration CreateRemoteConnectionConfiguration(); IFeatureConfiguration CreateRemoteConnectionConfiguration(Guid groupId);
/// <summary> /// <summary>
/// Creates an <see cref="IFeatureConfiguration"/> to control the option to sign out out via security screen. /// Creates an <see cref="IFeatureConfiguration"/> to control the option to sign out out via security screen.
/// </summary> /// </summary>
IFeatureConfiguration CreateSignoutConfiguration(); IFeatureConfiguration CreateSignoutConfiguration(Guid groupId);
/// <summary> /// <summary>
/// Creates an <see cref="IFeatureConfiguration"/> to control the task manager of Windows. /// Creates an <see cref="IFeatureConfiguration"/> to control the task manager of Windows.
/// </summary> /// </summary>
IFeatureConfiguration CreateTaskManagerConfiguration(); IFeatureConfiguration CreateTaskManagerConfiguration(Guid groupId);
/// <summary> /// <summary>
/// Creates an <see cref="IFeatureConfiguration"/> to control the option to lock the computer via the security screen. /// Creates an <see cref="IFeatureConfiguration"/> to control the option to lock the computer via the security screen.
/// </summary> /// </summary>
IFeatureConfiguration CreateUserLockConfiguration(); IFeatureConfiguration CreateUserLockConfiguration(Guid groupId);
/// <summary> /// <summary>
/// Creates an <see cref="IFeatureConfiguration"/> to control the option to switch to another user account via the security screen. /// Creates an <see cref="IFeatureConfiguration"/> to control the option to switch to another user account via the security screen.
/// </summary> /// </summary>
IFeatureConfiguration CreateUserSwitchConfiguration(); IFeatureConfiguration CreateUserSwitchConfiguration(Guid groupId);
/// <summary> /// <summary>
/// Creates an <see cref="IFeatureConfiguration"/> to control the user interface overlay for VMware clients. /// Creates an <see cref="IFeatureConfiguration"/> to control the user interface overlay for VMware clients.
/// </summary> /// </summary>
IFeatureConfiguration CreateVmwareOverlayConfiguration(); IFeatureConfiguration CreateVmwareOverlayConfiguration(Guid groupId);
/// <summary> /// <summary>
/// Creates an <see cref="IFeatureConfiguration"/> to control Windows Update. /// Creates an <see cref="IFeatureConfiguration"/> to control Windows Update.
/// </summary> /// </summary>
IFeatureConfiguration CreateWindowsUpdateConfiguration(); IFeatureConfiguration CreateWindowsUpdateConfiguration(Guid groupId);
} }
} }

View file

@ -92,6 +92,7 @@
<Compile Include="Applications\Events\NameChangedEventHandler.cs" /> <Compile Include="Applications\Events\NameChangedEventHandler.cs" />
<Compile Include="Applications\IApplicationController.cs" /> <Compile Include="Applications\IApplicationController.cs" />
<Compile Include="Applications\InstanceIdentifier.cs" /> <Compile Include="Applications\InstanceIdentifier.cs" />
<Compile Include="Lockdown\IAutoRestoreMechanism.cs" />
<Compile Include="Lockdown\IFeatureConfiguration.cs" /> <Compile Include="Lockdown\IFeatureConfiguration.cs" />
<Compile Include="Lockdown\IFeatureConfigurationBackup.cs" /> <Compile Include="Lockdown\IFeatureConfigurationBackup.cs" />
<Compile Include="Lockdown\IFeatureConfigurationFactory.cs" /> <Compile Include="Lockdown\IFeatureConfigurationFactory.cs" />

View file

@ -0,0 +1,32 @@
/*
* Copyright (c) 2019 ETH Zürich, Educational Development and Technology (LET)
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
using SafeExamBrowser.Contracts.Lockdown;
namespace SafeExamBrowser.Lockdown
{
public class AutoRestoreMechanism : IAutoRestoreMechanism
{
private IFeatureConfigurationBackup backup;
public AutoRestoreMechanism(IFeatureConfigurationBackup backup)
{
this.backup = backup;
}
public void Start()
{
}
public void Stop()
{
}
}
}

View file

@ -6,7 +6,12 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. * file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/ */
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using SafeExamBrowser.Contracts.Lockdown; using SafeExamBrowser.Contracts.Lockdown;
using SafeExamBrowser.Contracts.Logging; using SafeExamBrowser.Contracts.Logging;
@ -14,26 +19,114 @@ namespace SafeExamBrowser.Lockdown
{ {
public class FeatureConfigurationBackup : IFeatureConfigurationBackup public class FeatureConfigurationBackup : IFeatureConfigurationBackup
{ {
private ILogger logger; private readonly object @lock = new object();
public FeatureConfigurationBackup(ILogger logger) private string filePath;
private IModuleLogger logger;
public FeatureConfigurationBackup(string filePath, IModuleLogger logger)
{ {
this.filePath = filePath;
this.logger = logger; this.logger = logger;
} }
public void Delete(IFeatureConfiguration configuration) public void Delete(IFeatureConfiguration configuration)
{ {
lock (@lock)
{
var configurations = LoadFromFile();
var obsolete = configurations.Find(c => c.Id == configuration.Id);
if (obsolete != default(IFeatureConfiguration))
{
configurations.Remove(obsolete);
SaveToFile(configurations);
logger.Info($"Successfully removed {configuration} from backup.");
}
else
{
logger.Warn($"Could not delete {configuration} as it does not exists in backup!");
}
}
} }
public IList<IFeatureConfiguration> GetConfigurations() public IList<IFeatureConfiguration> GetAllConfigurations()
{ {
return new List<IFeatureConfiguration>(); lock (@lock)
{
return LoadFromFile();
}
}
public IList<IFeatureConfiguration> GetBy(Guid groupId)
{
lock (@lock)
{
return LoadFromFile().Where(c => c.GroupId == groupId).ToList();
}
} }
public void Save(IFeatureConfiguration configuration) public void Save(IFeatureConfiguration configuration)
{ {
lock (@lock)
{
var configurations = LoadFromFile();
configurations.Add(configuration);
SaveToFile(configurations);
logger.Info($"Successfully added {configuration} to backup.");
}
}
private void SaveToFile(List<IFeatureConfiguration> configurations)
{
try
{
logger.Debug($"Attempting to save backup data to '{filePath}'...");
using (var stream = File.Open(filePath, FileMode.Create))
{
new BinaryFormatter().Serialize(stream, configurations);
}
logger.Debug($"Successfully saved {configurations.Count} items.");
}
catch (Exception e)
{
logger.Error($"Failed to save backup data to '{filePath}'!", e);
}
}
private List<IFeatureConfiguration> LoadFromFile()
{
var configurations = new List<IFeatureConfiguration>();
try
{
if (File.Exists(filePath))
{
var context = new StreamingContext(StreamingContextStates.All, logger);
logger.Debug($"Attempting to load backup data from '{filePath}'...");
using (var stream = File.Open(filePath, FileMode.Open))
{
configurations = (List<IFeatureConfiguration>) new BinaryFormatter(null, context).Deserialize(stream);
}
logger.Debug($"Backup data successfully loaded, found {configurations.Count} items.");
}
else
{
logger.Debug($"No backup data found under '{filePath}'.");
}
}
catch (Exception e)
{
logger.Error($"Failed to load backup data from '{filePath}'!", e);
}
return configurations;
} }
} }
} }

View file

@ -6,6 +6,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. * file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/ */
using System;
using SafeExamBrowser.Contracts.Lockdown; using SafeExamBrowser.Contracts.Lockdown;
using SafeExamBrowser.Contracts.Logging; using SafeExamBrowser.Contracts.Logging;
using SafeExamBrowser.Lockdown.FeatureConfigurations; using SafeExamBrowser.Lockdown.FeatureConfigurations;
@ -21,64 +22,64 @@ namespace SafeExamBrowser.Lockdown
this.logger = logger; this.logger = logger;
} }
public IFeatureConfiguration CreateChromeNotificationConfiguration() public IFeatureConfiguration CreateChromeNotificationConfiguration(Guid groupId)
{ {
return new ChromeNotificationConfiguration(); return new ChromeNotificationConfiguration(groupId, logger.CloneFor(nameof(ChromeNotificationConfiguration)));
} }
public IFeatureConfiguration CreateEaseOfAccessConfiguration() public IFeatureConfiguration CreateEaseOfAccessConfiguration(Guid groupId)
{ {
return new EaseOfAccessConfiguration(); return new EaseOfAccessConfiguration(groupId, logger.CloneFor(nameof(EaseOfAccessConfiguration)));
} }
public IFeatureConfiguration CreateNetworkOptionsConfiguration() public IFeatureConfiguration CreateNetworkOptionsConfiguration(Guid groupId)
{ {
return new NetworkOptionsConfiguration(); return new NetworkOptionsConfiguration(groupId, logger.CloneFor(nameof(NetworkOptionsConfiguration)));
} }
public IFeatureConfiguration CreatePasswordChangeConfiguration() public IFeatureConfiguration CreatePasswordChangeConfiguration(Guid groupId)
{ {
return new PasswordChangeConfiguration(); return new PasswordChangeConfiguration(groupId, logger.CloneFor(nameof(PasswordChangeConfiguration)));
} }
public IFeatureConfiguration CreatePowerOptionsConfiguration() public IFeatureConfiguration CreatePowerOptionsConfiguration(Guid groupId)
{ {
return new PowerOptionsConfiguration(); return new PowerOptionsConfiguration(groupId, logger.CloneFor(nameof(PowerOptionsConfiguration)));
} }
public IFeatureConfiguration CreateRemoteConnectionConfiguration() public IFeatureConfiguration CreateRemoteConnectionConfiguration(Guid groupId)
{ {
return new RemoteConnectionConfiguration(); return new RemoteConnectionConfiguration(groupId, logger.CloneFor(nameof(RemoteConnectionConfiguration)));
} }
public IFeatureConfiguration CreateSignoutConfiguration() public IFeatureConfiguration CreateSignoutConfiguration(Guid groupId)
{ {
return new SignoutConfiguration(); return new SignoutConfiguration(groupId, logger.CloneFor(nameof(SignoutConfiguration)));
} }
public IFeatureConfiguration CreateTaskManagerConfiguration() public IFeatureConfiguration CreateTaskManagerConfiguration(Guid groupId)
{ {
return new TaskManagerConfiguration(); return new TaskManagerConfiguration(groupId, logger.CloneFor(nameof(TaskManagerConfiguration)));
} }
public IFeatureConfiguration CreateUserLockConfiguration() public IFeatureConfiguration CreateUserLockConfiguration(Guid groupId)
{ {
return new UserLockConfiguration(); return new UserLockConfiguration(groupId, logger.CloneFor(nameof(UserLockConfiguration)));
} }
public IFeatureConfiguration CreateUserSwitchConfiguration() public IFeatureConfiguration CreateUserSwitchConfiguration(Guid groupId)
{ {
return new UserSwitchConfiguration(); return new UserSwitchConfiguration(groupId, logger.CloneFor(nameof(UserSwitchConfiguration)));
} }
public IFeatureConfiguration CreateVmwareOverlayConfiguration() public IFeatureConfiguration CreateVmwareOverlayConfiguration(Guid groupId)
{ {
return new VmwareOverlayConfiguration(); return new VmwareOverlayConfiguration(groupId, logger.CloneFor(nameof(VmwareOverlayConfiguration)));
} }
public IFeatureConfiguration CreateWindowsUpdateConfiguration() public IFeatureConfiguration CreateWindowsUpdateConfiguration(Guid groupId)
{ {
return new WindowsUpdateConfiguration(); return new WindowsUpdateConfiguration(groupId, logger.CloneFor(nameof(WindowsUpdateConfiguration)));
} }
} }
} }

View file

@ -6,30 +6,36 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. * file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/ */
using SafeExamBrowser.Contracts.Lockdown; using System;
using SafeExamBrowser.Contracts.Logging;
namespace SafeExamBrowser.Lockdown.FeatureConfigurations namespace SafeExamBrowser.Lockdown.FeatureConfigurations
{ {
internal class ChromeNotificationConfiguration : IFeatureConfiguration [Serializable]
internal class ChromeNotificationConfiguration : FeatureConfiguration
{ {
public void DisableFeature() public ChromeNotificationConfiguration(Guid groupId, ILogger logger) : base(groupId, logger)
{ {
} }
public void EnableFeature() public override void DisableFeature()
{ {
logger.Info("Disabling...");
} }
public void Monitor() public override void EnableFeature()
{ {
logger.Info("Enabling...");
} }
public void Restore() public override void Monitor()
{ {
logger.Info("Monitoring...");
}
public override void Restore()
{
logger.Info("Restoring...");
} }
} }
} }

View file

@ -6,28 +6,34 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. * file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/ */
using SafeExamBrowser.Contracts.Lockdown; using System;
using SafeExamBrowser.Contracts.Logging;
namespace SafeExamBrowser.Lockdown.FeatureConfigurations namespace SafeExamBrowser.Lockdown.FeatureConfigurations
{ {
internal class EaseOfAccessConfiguration : IFeatureConfiguration [Serializable]
internal class EaseOfAccessConfiguration : FeatureConfiguration
{ {
public void DisableFeature() public EaseOfAccessConfiguration(Guid groupId, ILogger logger) : base(groupId, logger)
{
}
public override void DisableFeature()
{ {
} }
public void EnableFeature() public override void EnableFeature()
{ {
} }
public void Monitor() public override void Monitor()
{ {
} }
public void Restore() public override void Restore()
{ {
} }

View file

@ -0,0 +1,48 @@
/*
* Copyright (c) 2019 ETH Zürich, Educational Development and Technology (LET)
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
using System;
using System.Runtime.Serialization;
using SafeExamBrowser.Contracts.Lockdown;
using SafeExamBrowser.Contracts.Logging;
namespace SafeExamBrowser.Lockdown.FeatureConfigurations
{
[Serializable]
internal abstract class FeatureConfiguration : IFeatureConfiguration
{
[NonSerialized]
protected ILogger logger;
public Guid Id { get; }
public Guid GroupId { get; }
public FeatureConfiguration(Guid groupId, ILogger logger)
{
this.GroupId = groupId;
this.Id = Guid.NewGuid();
this.logger = logger;
}
public abstract void DisableFeature();
public abstract void EnableFeature();
public abstract void Monitor();
public abstract void Restore();
public override string ToString()
{
return $"{GetType().Name} ({Id})";
}
[OnDeserialized]
private void OnDeserializedMethod(StreamingContext context)
{
logger = (context.Context as IModuleLogger).CloneFor(GetType().Name);
}
}
}

View file

@ -6,28 +6,34 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. * file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/ */
using SafeExamBrowser.Contracts.Lockdown; using System;
using SafeExamBrowser.Contracts.Logging;
namespace SafeExamBrowser.Lockdown.FeatureConfigurations namespace SafeExamBrowser.Lockdown.FeatureConfigurations
{ {
internal class NetworkOptionsConfiguration : IFeatureConfiguration [Serializable]
internal class NetworkOptionsConfiguration : FeatureConfiguration
{ {
public void DisableFeature() public NetworkOptionsConfiguration(Guid groupId, ILogger logger) : base(groupId, logger)
{
}
public override void DisableFeature()
{ {
} }
public void EnableFeature() public override void EnableFeature()
{ {
} }
public void Monitor() public override void Monitor()
{ {
} }
public void Restore() public override void Restore()
{ {
} }

View file

@ -6,28 +6,34 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. * file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/ */
using SafeExamBrowser.Contracts.Lockdown; using System;
using SafeExamBrowser.Contracts.Logging;
namespace SafeExamBrowser.Lockdown.FeatureConfigurations namespace SafeExamBrowser.Lockdown.FeatureConfigurations
{ {
internal class PasswordChangeConfiguration : IFeatureConfiguration [Serializable]
internal class PasswordChangeConfiguration : FeatureConfiguration
{ {
public void DisableFeature() public PasswordChangeConfiguration(Guid groupId, ILogger logger) : base(groupId, logger)
{
}
public override void DisableFeature()
{ {
} }
public void EnableFeature() public override void EnableFeature()
{ {
} }
public void Monitor() public override void Monitor()
{ {
} }
public void Restore() public override void Restore()
{ {
} }

View file

@ -6,28 +6,34 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. * file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/ */
using SafeExamBrowser.Contracts.Lockdown; using System;
using SafeExamBrowser.Contracts.Logging;
namespace SafeExamBrowser.Lockdown.FeatureConfigurations namespace SafeExamBrowser.Lockdown.FeatureConfigurations
{ {
internal class PowerOptionsConfiguration : IFeatureConfiguration [Serializable]
internal class PowerOptionsConfiguration : FeatureConfiguration
{ {
public void DisableFeature() public PowerOptionsConfiguration(Guid groupId, ILogger logger) : base(groupId, logger)
{
}
public override void DisableFeature()
{ {
} }
public void EnableFeature() public override void EnableFeature()
{ {
} }
public void Monitor() public override void Monitor()
{ {
} }
public void Restore() public override void Restore()
{ {
} }

View file

@ -6,28 +6,34 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. * file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/ */
using SafeExamBrowser.Contracts.Lockdown; using System;
using SafeExamBrowser.Contracts.Logging;
namespace SafeExamBrowser.Lockdown.FeatureConfigurations namespace SafeExamBrowser.Lockdown.FeatureConfigurations
{ {
internal class RemoteConnectionConfiguration : IFeatureConfiguration [Serializable]
internal class RemoteConnectionConfiguration : FeatureConfiguration
{ {
public void DisableFeature() public RemoteConnectionConfiguration(Guid groupId, ILogger logger) : base(groupId, logger)
{
}
public override void DisableFeature()
{ {
} }
public void EnableFeature() public override void EnableFeature()
{ {
} }
public void Monitor() public override void Monitor()
{ {
} }
public void Restore() public override void Restore()
{ {
} }

View file

@ -6,28 +6,34 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. * file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/ */
using SafeExamBrowser.Contracts.Lockdown; using System;
using SafeExamBrowser.Contracts.Logging;
namespace SafeExamBrowser.Lockdown.FeatureConfigurations namespace SafeExamBrowser.Lockdown.FeatureConfigurations
{ {
internal class SignoutConfiguration : IFeatureConfiguration [Serializable]
internal class SignoutConfiguration : FeatureConfiguration
{ {
public void DisableFeature() public SignoutConfiguration(Guid groupId, ILogger logger) : base(groupId, logger)
{
}
public override void DisableFeature()
{ {
} }
public void EnableFeature() public override void EnableFeature()
{ {
} }
public void Monitor() public override void Monitor()
{ {
} }
public void Restore() public override void Restore()
{ {
} }

View file

@ -6,28 +6,34 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. * file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/ */
using SafeExamBrowser.Contracts.Lockdown; using System;
using SafeExamBrowser.Contracts.Logging;
namespace SafeExamBrowser.Lockdown.FeatureConfigurations namespace SafeExamBrowser.Lockdown.FeatureConfigurations
{ {
internal class TaskManagerConfiguration : IFeatureConfiguration [Serializable]
internal class TaskManagerConfiguration : FeatureConfiguration
{ {
public void DisableFeature() public TaskManagerConfiguration(Guid groupId, ILogger logger) : base(groupId, logger)
{
}
public override void DisableFeature()
{ {
} }
public void EnableFeature() public override void EnableFeature()
{ {
} }
public void Monitor() public override void Monitor()
{ {
} }
public void Restore() public override void Restore()
{ {
} }

View file

@ -6,28 +6,34 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. * file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/ */
using SafeExamBrowser.Contracts.Lockdown; using System;
using SafeExamBrowser.Contracts.Logging;
namespace SafeExamBrowser.Lockdown.FeatureConfigurations namespace SafeExamBrowser.Lockdown.FeatureConfigurations
{ {
internal class UserLockConfiguration : IFeatureConfiguration [Serializable]
internal class UserLockConfiguration : FeatureConfiguration
{ {
public void DisableFeature() public UserLockConfiguration(Guid groupId, ILogger logger) : base(groupId, logger)
{
}
public override void DisableFeature()
{ {
} }
public void EnableFeature() public override void EnableFeature()
{ {
} }
public void Monitor() public override void Monitor()
{ {
} }
public void Restore() public override void Restore()
{ {
} }

View file

@ -6,28 +6,34 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. * file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/ */
using SafeExamBrowser.Contracts.Lockdown; using System;
using SafeExamBrowser.Contracts.Logging;
namespace SafeExamBrowser.Lockdown.FeatureConfigurations namespace SafeExamBrowser.Lockdown.FeatureConfigurations
{ {
internal class UserSwitchConfiguration : IFeatureConfiguration [Serializable]
internal class UserSwitchConfiguration : FeatureConfiguration
{ {
public void DisableFeature() public UserSwitchConfiguration(Guid groupId, ILogger logger) : base(groupId, logger)
{
}
public override void DisableFeature()
{ {
} }
public void EnableFeature() public override void EnableFeature()
{ {
} }
public void Monitor() public override void Monitor()
{ {
} }
public void Restore() public override void Restore()
{ {
} }

View file

@ -6,28 +6,34 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. * file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/ */
using SafeExamBrowser.Contracts.Lockdown; using System;
using SafeExamBrowser.Contracts.Logging;
namespace SafeExamBrowser.Lockdown.FeatureConfigurations namespace SafeExamBrowser.Lockdown.FeatureConfigurations
{ {
internal class VmwareOverlayConfiguration : IFeatureConfiguration [Serializable]
internal class VmwareOverlayConfiguration : FeatureConfiguration
{ {
public void DisableFeature() public VmwareOverlayConfiguration(Guid groupId, ILogger logger) : base(groupId, logger)
{
}
public override void DisableFeature()
{ {
} }
public void EnableFeature() public override void EnableFeature()
{ {
} }
public void Monitor() public override void Monitor()
{ {
} }
public void Restore() public override void Restore()
{ {
} }

View file

@ -6,28 +6,34 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. * file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/ */
using SafeExamBrowser.Contracts.Lockdown; using System;
using SafeExamBrowser.Contracts.Logging;
namespace SafeExamBrowser.Lockdown.FeatureConfigurations namespace SafeExamBrowser.Lockdown.FeatureConfigurations
{ {
internal class WindowsUpdateConfiguration : IFeatureConfiguration [Serializable]
internal class WindowsUpdateConfiguration : FeatureConfiguration
{ {
public void DisableFeature() public WindowsUpdateConfiguration(Guid groupId, ILogger logger) : base(groupId, logger)
{
}
public override void DisableFeature()
{ {
} }
public void EnableFeature() public override void EnableFeature()
{ {
} }
public void Monitor() public override void Monitor()
{ {
} }
public void Restore() public override void Restore()
{ {
} }

View file

@ -53,9 +53,11 @@
<Reference Include="Microsoft.CSharp" /> <Reference Include="Microsoft.CSharp" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="AutoRestoreMechanism.cs" />
<Compile Include="FeatureConfigurationFactory.cs" /> <Compile Include="FeatureConfigurationFactory.cs" />
<Compile Include="FeatureConfigurationBackup.cs" /> <Compile Include="FeatureConfigurationBackup.cs" />
<Compile Include="FeatureConfigurations\ChromeNotificationConfiguration.cs" /> <Compile Include="FeatureConfigurations\ChromeNotificationConfiguration.cs" />
<Compile Include="FeatureConfigurations\FeatureConfiguration.cs" />
<Compile Include="FeatureConfigurations\TaskManagerConfiguration.cs" /> <Compile Include="FeatureConfigurations\TaskManagerConfiguration.cs" />
<Compile Include="FeatureConfigurations\EaseOfAccessConfiguration.cs" /> <Compile Include="FeatureConfigurations\EaseOfAccessConfiguration.cs" />
<Compile Include="FeatureConfigurations\NetworkOptionsConfiguration.cs" /> <Compile Include="FeatureConfigurations\NetworkOptionsConfiguration.cs" />

View file

@ -14,6 +14,7 @@ using Moq;
using SafeExamBrowser.Contracts.Communication.Hosts; using SafeExamBrowser.Contracts.Communication.Hosts;
using SafeExamBrowser.Contracts.Configuration; using SafeExamBrowser.Contracts.Configuration;
using SafeExamBrowser.Contracts.Core.OperationModel; using SafeExamBrowser.Contracts.Core.OperationModel;
using SafeExamBrowser.Contracts.Lockdown;
using SafeExamBrowser.Contracts.Logging; using SafeExamBrowser.Contracts.Logging;
using SafeExamBrowser.Service.Operations; using SafeExamBrowser.Service.Operations;
@ -22,6 +23,7 @@ namespace SafeExamBrowser.Service.UnitTests.Operations
[TestClass] [TestClass]
public class SessionInitializationOperationTests public class SessionInitializationOperationTests
{ {
private Mock<IAutoRestoreMechanism> autoRestoreMechanism;
private Mock<ILogger> logger; private Mock<ILogger> logger;
private Mock<Func<string, ILogObserver>> logWriterFactory; private Mock<Func<string, ILogObserver>> logWriterFactory;
private Mock<IServiceHost> serviceHost; private Mock<IServiceHost> serviceHost;
@ -32,6 +34,7 @@ namespace SafeExamBrowser.Service.UnitTests.Operations
[TestInitialize] [TestInitialize]
public void Initialize() public void Initialize()
{ {
autoRestoreMechanism = new Mock<IAutoRestoreMechanism>();
logger = new Mock<ILogger>(); logger = new Mock<ILogger>();
logWriterFactory = new Mock<Func<string, ILogObserver>>(); logWriterFactory = new Mock<Func<string, ILogObserver>>();
serviceHost = new Mock<IServiceHost>(); serviceHost = new Mock<IServiceHost>();
@ -40,6 +43,7 @@ namespace SafeExamBrowser.Service.UnitTests.Operations
logWriterFactory.Setup(f => f.Invoke(It.IsAny<string>())).Returns(new Mock<ILogObserver>().Object); logWriterFactory.Setup(f => f.Invoke(It.IsAny<string>())).Returns(new Mock<ILogObserver>().Object);
serviceEventFactory.Setup(f => f.Invoke(It.IsAny<string>())).Returns(new EventStub()); serviceEventFactory.Setup(f => f.Invoke(It.IsAny<string>())).Returns(new EventStub());
sessionContext.AutoRestoreMechanism = autoRestoreMechanism.Object;
sessionContext.Configuration = new ServiceConfiguration sessionContext.Configuration = new ServiceConfiguration
{ {
AppConfig = new AppConfig { ServiceEventName = $"{nameof(SafeExamBrowser)}-{nameof(SessionInitializationOperationTests)}" } AppConfig = new AppConfig { ServiceEventName = $"{nameof(SafeExamBrowser)}-{nameof(SessionInitializationOperationTests)}" }
@ -74,18 +78,12 @@ namespace SafeExamBrowser.Service.UnitTests.Operations
} }
[TestMethod] [TestMethod]
public void Revert_MustSetServiceEvent() public void Perform_MustStopAutoRestoreMechanism()
{ {
sessionContext.ServiceEvent = new EventWaitHandle(false, EventResetMode.AutoReset); var result = sut.Perform();
var wasSet = false;
var task = Task.Run(() => wasSet = sessionContext.ServiceEvent.WaitOne(1000));
var result = sut.Revert();
task.Wait();
autoRestoreMechanism.Verify(m => m.Stop(), Times.Once);
Assert.AreEqual(OperationResult.Success, result); Assert.AreEqual(OperationResult.Success, result);
Assert.IsTrue(wasSet);
} }
[TestMethod] [TestMethod]
@ -110,5 +108,29 @@ namespace SafeExamBrowser.Service.UnitTests.Operations
serviceHost.VerifySet(h => h.AllowConnection = true, Times.Once); serviceHost.VerifySet(h => h.AllowConnection = true, Times.Once);
Assert.AreEqual(OperationResult.Success, result); Assert.AreEqual(OperationResult.Success, result);
} }
[TestMethod]
public void Revert_MustSetServiceEvent()
{
sessionContext.ServiceEvent = new EventWaitHandle(false, EventResetMode.AutoReset);
var wasSet = false;
var task = Task.Run(() => wasSet = sessionContext.ServiceEvent.WaitOne(1000));
var result = sut.Revert();
task.Wait();
Assert.AreEqual(OperationResult.Success, result);
Assert.IsTrue(wasSet);
}
[TestMethod]
public void Revert_MustStartAutoRestoreMechanism()
{
var result = sut.Revert();
autoRestoreMechanism.Verify(m => m.Start(), Times.Once);
Assert.AreEqual(OperationResult.Success, result);
}
} }
} }

View file

@ -14,6 +14,7 @@ using System.Security.Principal;
using System.Threading; using System.Threading;
using SafeExamBrowser.Communication.Hosts; using SafeExamBrowser.Communication.Hosts;
using SafeExamBrowser.Communication.Proxies; using SafeExamBrowser.Communication.Proxies;
using SafeExamBrowser.Contracts.Configuration;
using SafeExamBrowser.Contracts.Core.OperationModel; using SafeExamBrowser.Contracts.Core.OperationModel;
using SafeExamBrowser.Contracts.Logging; using SafeExamBrowser.Contracts.Logging;
using SafeExamBrowser.Contracts.Service; using SafeExamBrowser.Contracts.Service;
@ -34,21 +35,23 @@ namespace SafeExamBrowser.Service
internal void BuildObjectGraph() internal void BuildObjectGraph()
{ {
const string SERVICE_ADDRESS = "net.pipe://localhost/safeexambrowser/service";
const int FIVE_SECONDS = 5000; const int FIVE_SECONDS = 5000;
var backupFile = BuildBackupFilePath();
InitializeLogging(); InitializeLogging();
var featureBackup = new FeatureConfigurationBackup(new ModuleLogger(logger, nameof(FeatureConfigurationBackup))); var featureBackup = new FeatureConfigurationBackup(backupFile, new ModuleLogger(logger, nameof(FeatureConfigurationBackup)));
var featureFactory = new FeatureConfigurationFactory(new ModuleLogger(logger, nameof(FeatureConfigurationFactory))); var featureFactory = new FeatureConfigurationFactory(new ModuleLogger(logger, nameof(FeatureConfigurationFactory)));
var proxyFactory = new ProxyFactory(new ProxyObjectFactory(), new ModuleLogger(logger, nameof(ProxyFactory))); var proxyFactory = new ProxyFactory(new ProxyObjectFactory(), new ModuleLogger(logger, nameof(ProxyFactory)));
var serviceHost = new ServiceHost(SERVICE_ADDRESS, new HostObjectFactory(), new ModuleLogger(logger, nameof(ServiceHost)), FIVE_SECONDS); var serviceHost = new ServiceHost(AppConfig.SERVICE_ADDRESS, new HostObjectFactory(), new ModuleLogger(logger, nameof(ServiceHost)), FIVE_SECONDS);
var sessionContext = new SessionContext(); var sessionContext = new SessionContext();
var bootstrapOperations = new Queue<IOperation>(); var bootstrapOperations = new Queue<IOperation>();
var sessionOperations = new Queue<IOperation>(); var sessionOperations = new Queue<IOperation>();
bootstrapOperations.Enqueue(new RestoreOperation(logger)); sessionContext.AutoRestoreMechanism = new AutoRestoreMechanism(featureBackup);
bootstrapOperations.Enqueue(new RestoreOperation(featureBackup, logger, sessionContext));
bootstrapOperations.Enqueue(new CommunicationHostOperation(serviceHost, logger)); bootstrapOperations.Enqueue(new CommunicationHostOperation(serviceHost, logger));
bootstrapOperations.Enqueue(new ServiceEventCleanupOperation(logger, sessionContext)); bootstrapOperations.Enqueue(new ServiceEventCleanupOperation(logger, sessionContext));
@ -62,6 +65,14 @@ namespace SafeExamBrowser.Service
ServiceController = new ServiceController(logger, bootstrapSequence, sessionSequence, serviceHost, sessionContext); ServiceController = new ServiceController(logger, bootstrapSequence, sessionSequence, serviceHost, sessionContext);
} }
private string BuildBackupFilePath()
{
var appDataFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), nameof(SafeExamBrowser));
var filePath = Path.Combine(appDataFolder, AppConfig.BACKUP_FILE_NAME);
return filePath;
}
internal void LogStartupInformation() internal void LogStartupInformation()
{ {
logger.Log($"# Service started at {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}"); logger.Log($"# Service started at {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}");

View file

@ -6,6 +6,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. * file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/ */
using System;
using SafeExamBrowser.Contracts.Core.OperationModel; using SafeExamBrowser.Contracts.Core.OperationModel;
using SafeExamBrowser.Contracts.Lockdown; using SafeExamBrowser.Contracts.Lockdown;
using SafeExamBrowser.Contracts.Logging; using SafeExamBrowser.Contracts.Logging;
@ -17,6 +18,7 @@ namespace SafeExamBrowser.Service.Operations
private IFeatureConfigurationBackup backup; private IFeatureConfigurationBackup backup;
private IFeatureConfigurationFactory factory; private IFeatureConfigurationFactory factory;
private ILogger logger; private ILogger logger;
private Guid groupId;
public LockdownOperation( public LockdownOperation(
IFeatureConfigurationBackup backup, IFeatureConfigurationBackup backup,
@ -31,18 +33,21 @@ namespace SafeExamBrowser.Service.Operations
public override OperationResult Perform() public override OperationResult Perform()
{ {
var chromeNotification = factory.CreateChromeNotificationConfiguration(); groupId = Guid.NewGuid();
var easeOfAccess = factory.CreateEaseOfAccessConfiguration(); logger.Info($"Attempting to perform lockdown (feature configuration group: {groupId})...");
var networkOptions = factory.CreateNetworkOptionsConfiguration();
var passwordChange = factory.CreatePasswordChangeConfiguration(); var chromeNotification = factory.CreateChromeNotificationConfiguration(groupId);
var powerOptions = factory.CreatePowerOptionsConfiguration(); var easeOfAccess = factory.CreateEaseOfAccessConfiguration(groupId);
var remoteConnection = factory.CreateRemoteConnectionConfiguration(); var networkOptions = factory.CreateNetworkOptionsConfiguration(groupId);
var signout = factory.CreateSignoutConfiguration(); var passwordChange = factory.CreatePasswordChangeConfiguration(groupId);
var taskManager = factory.CreateTaskManagerConfiguration(); var powerOptions = factory.CreatePowerOptionsConfiguration(groupId);
var userLock = factory.CreateUserLockConfiguration(); var remoteConnection = factory.CreateRemoteConnectionConfiguration(groupId);
var userSwitch = factory.CreateUserSwitchConfiguration(); var signout = factory.CreateSignoutConfiguration(groupId);
var vmwareOverlay = factory.CreateVmwareOverlayConfiguration(); var taskManager = factory.CreateTaskManagerConfiguration(groupId);
var windowsUpdate = factory.CreateWindowsUpdateConfiguration(); var userLock = factory.CreateUserLockConfiguration(groupId);
var userSwitch = factory.CreateUserSwitchConfiguration(groupId);
var vmwareOverlay = factory.CreateVmwareOverlayConfiguration(groupId);
var windowsUpdate = factory.CreateWindowsUpdateConfiguration(groupId);
SetConfiguration(chromeNotification, Context.Configuration.Settings.Service.DisableChromeNotifications); SetConfiguration(chromeNotification, Context.Configuration.Settings.Service.DisableChromeNotifications);
SetConfiguration(easeOfAccess, Context.Configuration.Settings.Service.DisableEaseOfAccessOptions); SetConfiguration(easeOfAccess, Context.Configuration.Settings.Service.DisableEaseOfAccessOptions);
@ -57,12 +62,16 @@ namespace SafeExamBrowser.Service.Operations
SetConfiguration(vmwareOverlay, Context.Configuration.Settings.Service.DisableVmwareOverlay); SetConfiguration(vmwareOverlay, Context.Configuration.Settings.Service.DisableVmwareOverlay);
SetConfiguration(windowsUpdate, Context.Configuration.Settings.Service.DisableWindowsUpdate); SetConfiguration(windowsUpdate, Context.Configuration.Settings.Service.DisableWindowsUpdate);
logger.Info("Lockdown successful.");
return OperationResult.Success; return OperationResult.Success;
} }
public override OperationResult Revert() public override OperationResult Revert()
{ {
var configurations = backup.GetConfigurations(); logger.Info($"Attempting to revert lockdown (feature configuration group: {groupId})...");
var configurations = backup.GetBy(groupId);
foreach (var configuration in configurations) foreach (var configuration in configurations)
{ {
@ -70,6 +79,8 @@ namespace SafeExamBrowser.Service.Operations
backup.Delete(configuration); backup.Delete(configuration);
} }
logger.Info("Lockdown reversion successful.");
return OperationResult.Success; return OperationResult.Success;
} }

View file

@ -8,32 +8,40 @@
using SafeExamBrowser.Contracts.Core.OperationModel; using SafeExamBrowser.Contracts.Core.OperationModel;
using SafeExamBrowser.Contracts.Core.OperationModel.Events; using SafeExamBrowser.Contracts.Core.OperationModel.Events;
using SafeExamBrowser.Contracts.Lockdown;
using SafeExamBrowser.Contracts.Logging; using SafeExamBrowser.Contracts.Logging;
namespace SafeExamBrowser.Service.Operations namespace SafeExamBrowser.Service.Operations
{ {
internal class RestoreOperation : IOperation internal class RestoreOperation : IOperation
{ {
private readonly IFeatureConfigurationBackup backup;
private ILogger logger; private ILogger logger;
private readonly SessionContext sessionContext;
public event ActionRequiredEventHandler ActionRequired { add { } remove { } } public event ActionRequiredEventHandler ActionRequired { add { } remove { } }
public event StatusChangedEventHandler StatusChanged { add { } remove { } } public event StatusChangedEventHandler StatusChanged { add { } remove { } }
public RestoreOperation(ILogger logger) public RestoreOperation(IFeatureConfigurationBackup backup, ILogger logger, SessionContext sessionContext)
{ {
this.backup = backup;
this.logger = logger; this.logger = logger;
this.sessionContext = sessionContext;
} }
public OperationResult Perform() public OperationResult Perform()
{ {
// TODO: Must not delay startup! If restore does not succeed on first attempt, try again in separate thread! logger.Info("Starting auto-restore mechanism...");
// -> Ensure session cannot be started until values are restored or alike! sessionContext.AutoRestoreMechanism.Start();
return OperationResult.Success; return OperationResult.Success;
} }
public OperationResult Revert() public OperationResult Revert()
{ {
logger.Info("Stopping auto-restore mechanism...");
sessionContext.AutoRestoreMechanism.Stop();
return OperationResult.Success; return OperationResult.Success;
} }
} }

View file

@ -40,12 +40,16 @@ namespace SafeExamBrowser.Service.Operations
InitializeSessionWriter(); InitializeSessionWriter();
logger.Info("Initializing new session..."); logger.Info("Initializing new session...");
serviceHost.AllowConnection = false;
logger.Info($" -> Client-ID: {Context.Configuration.AppConfig.ClientId}"); logger.Info($" -> Client-ID: {Context.Configuration.AppConfig.ClientId}");
logger.Info($" -> Runtime-ID: {Context.Configuration.AppConfig.RuntimeId}"); logger.Info($" -> Runtime-ID: {Context.Configuration.AppConfig.RuntimeId}");
logger.Info($" -> Session-ID: {Context.Configuration.SessionId}"); logger.Info($" -> Session-ID: {Context.Configuration.SessionId}");
logger.Info("Stopping auto-restore mechanism...");
Context.AutoRestoreMechanism.Stop();
logger.Info("Disabling service host...");
serviceHost.AllowConnection = false;
InitializeServiceEvent(); InitializeServiceEvent();
return OperationResult.Success; return OperationResult.Success;
@ -71,11 +75,17 @@ namespace SafeExamBrowser.Service.Operations
} }
} }
Context.Configuration = null; logger.Info("Starting auto-restore mechanism...");
logger.Unsubscribe(sessionWriter); Context.AutoRestoreMechanism.Start();
sessionWriter = null;
logger.Info("Enabling service host...");
serviceHost.AllowConnection = true; serviceHost.AllowConnection = true;
logger.Info("Clearing session data...");
Context.Configuration = null;
FinalizeSessionWriter();
return success ? OperationResult.Success : OperationResult.Failed; return success ? OperationResult.Success : OperationResult.Failed;
} }
@ -97,6 +107,14 @@ namespace SafeExamBrowser.Service.Operations
{ {
sessionWriter = logWriterFactory.Invoke(Context.Configuration.AppConfig.ServiceLogFilePath); sessionWriter = logWriterFactory.Invoke(Context.Configuration.AppConfig.ServiceLogFilePath);
logger.Subscribe(sessionWriter); logger.Subscribe(sessionWriter);
logger.Debug($"Created session log file {Context.Configuration.AppConfig.ServiceLogFilePath}.");
}
private void FinalizeSessionWriter()
{
logger.Debug("Closed session log file.");
logger.Unsubscribe(sessionWriter);
sessionWriter = null;
} }
} }
} }

View file

@ -8,6 +8,7 @@
using System.Threading; using System.Threading;
using SafeExamBrowser.Contracts.Configuration; using SafeExamBrowser.Contracts.Configuration;
using SafeExamBrowser.Contracts.Lockdown;
namespace SafeExamBrowser.Service namespace SafeExamBrowser.Service
{ {
@ -16,6 +17,11 @@ namespace SafeExamBrowser.Service
/// </summary> /// </summary>
internal class SessionContext internal class SessionContext
{ {
/// <summary>
/// The mechanism trying to restore all changes after an application or system failure.
/// </summary>
internal IAutoRestoreMechanism AutoRestoreMechanism { get; set; }
/// <summary> /// <summary>
/// The configuration of the currently active session. /// The configuration of the currently active session.
/// </summary> /// </summary>