SEBWIN-301: Implemented service log file persistence in user directory.

This commit is contained in:
dbuechel 2019-06-18 15:51:35 +02:00
parent 6b24554abc
commit 3589b92b9d
8 changed files with 61 additions and 22 deletions

View file

@ -68,6 +68,8 @@ namespace SafeExamBrowser.Configuration.ConfigurationData
appConfig.SebUriScheme = "seb";
appConfig.SebUriSchemeSecure = "sebs";
appConfig.ServiceAddress = $"{BASE_ADDRESS}/service";
appConfig.ServiceEventName = $@"Global\{nameof(SafeExamBrowser)}-{Guid.NewGuid()}";
appConfig.ServiceLogFilePath = Path.Combine(logFolder, $"{logFilePrefix}_Service.log");
return appConfig;
}

View file

@ -121,6 +121,11 @@ namespace SafeExamBrowser.Contracts.Configuration
/// </summary>
public string ServiceEventName { get; set; }
/// <summary>
/// The file path under which the log for the current session of the service component is to be stored.
/// </summary>
public string ServiceLogFilePath { get; set; }
/// <summary>
/// Creates a shallow clone.
/// </summary>

View file

@ -29,11 +29,11 @@ namespace SafeExamBrowser.Logging
public void Initialize()
{
var logFolder = Path.GetDirectoryName(filePath);
var directory = Path.GetDirectoryName(filePath);
if (!Directory.Exists(logFolder))
if (!Directory.Exists(directory))
{
Directory.CreateDirectory(logFolder);
Directory.CreateDirectory(directory);
}
}

View file

@ -46,7 +46,7 @@ namespace SafeExamBrowser.Service
bootstrapOperations.Enqueue(new CommunicationHostOperation(serviceHost, logger));
bootstrapOperations.Enqueue(new ServiceEventCleanupOperation(logger, sessionContext));
sessionOperations.Enqueue(new SessionInitializationOperation(logger, serviceHost, sessionContext));
sessionOperations.Enqueue(new SessionInitializationOperation(logger, CreateLogWriter, serviceHost, sessionContext));
// TODO: sessionOperations.Enqueue(new RegistryOperation());
// sessionOperations.Enqueue(new WindowsUpdateOperation());
sessionOperations.Enqueue(new SessionActivationOperation(logger, sessionContext));
@ -81,5 +81,14 @@ namespace SafeExamBrowser.Service
logger.Subscribe(logFileWriter);
logFileWriter.Initialize();
}
private ILogObserver CreateLogWriter(string filePath)
{
var writer = new LogFileWriter(new DefaultLogFormatter(), filePath);
writer.Initialize();
return writer;
}
}
}

View file

@ -33,10 +33,10 @@ namespace SafeExamBrowser.Service.Operations
public OperationResult Revert()
{
if (sessionContext.EventWaitHandle != null)
if (sessionContext.ServiceEvent != null)
{
logger.Info("Closing service event...");
sessionContext.EventWaitHandle.Close();
sessionContext.ServiceEvent.Close();
logger.Info("Service event successfully closed.");
}

View file

@ -22,7 +22,7 @@ namespace SafeExamBrowser.Service.Operations
public override OperationResult Perform()
{
var success = Context.EventWaitHandle.Set();
var success = Context.ServiceEvent.Set();
if (success)
{

View file

@ -6,6 +6,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
using System;
using System.Security.AccessControl;
using System.Security.Principal;
using System.Threading;
@ -18,16 +19,25 @@ namespace SafeExamBrowser.Service.Operations
internal class SessionInitializationOperation : SessionOperation
{
private ILogger logger;
private Func<string, ILogObserver> createLogWriter;
private IServiceHost serviceHost;
private ILogObserver sessionWriter;
public SessionInitializationOperation(ILogger logger, IServiceHost serviceHost, SessionContext sessionContext) : base(sessionContext)
public SessionInitializationOperation(
ILogger logger,
Func<string, ILogObserver> createLogWriter,
IServiceHost serviceHost,
SessionContext sessionContext) : base(sessionContext)
{
this.logger = logger;
this.createLogWriter = createLogWriter;
this.serviceHost = serviceHost;
}
public override OperationResult Perform()
{
InitializeSessionWriter();
logger.Info("Initializing new session...");
serviceHost.AllowConnection = false;
@ -35,33 +45,40 @@ namespace SafeExamBrowser.Service.Operations
logger.Info($" -> Runtime-ID: {Context.Configuration.AppConfig.RuntimeId}");
logger.Info($" -> Session-ID: {Context.Configuration.SessionId}");
InitializeEventWaitHandle();
InitializeServiceEvent();
return OperationResult.Success;
}
public override OperationResult Revert()
{
var success = true;
logger.Info("Finalizing current session...");
var success = Context.EventWaitHandle?.Set() == true;
if (Context.ServiceEvent != null)
{
success = Context.ServiceEvent.Set();
if (success)
{
logger.Info("Successfully informed runtime about session termination.");
}
else
{
logger.Error("Failed to inform runtime about session termination!");
if (success)
{
logger.Info("Successfully informed runtime about session termination.");
}
else
{
logger.Error("Failed to inform runtime about session termination!");
}
}
Context.Configuration = null;
logger.Unsubscribe(sessionWriter);
sessionWriter = null;
serviceHost.AllowConnection = true;
return success ? OperationResult.Success : OperationResult.Failed;
}
private void InitializeEventWaitHandle()
private void InitializeServiceEvent()
{
var securityIdentifier = new SecurityIdentifier(WellKnownSidType.BuiltinUsersSid, null);
var accessRule = new EventWaitHandleAccessRule(securityIdentifier, EventWaitHandleRights.Synchronize, AccessControlType.Allow);
@ -69,16 +86,22 @@ namespace SafeExamBrowser.Service.Operations
security.AddAccessRule(accessRule);
if (Context.EventWaitHandle != null)
if (Context.ServiceEvent != null)
{
logger.Info("Closing service event from previous session...");
Context.EventWaitHandle.Close();
Context.ServiceEvent.Close();
logger.Info("Service event successfully closed.");
}
logger.Info("Attempting to create new service event...");
Context.EventWaitHandle = new EventWaitHandle(false, EventResetMode.AutoReset, Context.Configuration.AppConfig.ServiceEventName, out _, security);
Context.ServiceEvent = new EventWaitHandle(false, EventResetMode.AutoReset, Context.Configuration.AppConfig.ServiceEventName, out _, security);
logger.Info("Service event successfully created.");
}
private void InitializeSessionWriter()
{
sessionWriter = createLogWriter.Invoke(Context.Configuration.AppConfig.ServiceLogFilePath);
logger.Subscribe(sessionWriter);
}
}
}

View file

@ -24,6 +24,6 @@ namespace SafeExamBrowser.Service
/// <summary>
/// The global inter-process event used for status synchronization with the runtime component.
/// </summary>
internal EventWaitHandle EventWaitHandle { get; set; }
internal EventWaitHandle ServiceEvent { get; set; }
}
}