/* ========================================================================
* Copyright (c) 2005-2025 The OPC Foundation, Inc. All rights reserved.
*
* OPC Foundation MIT License 1.00
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* The complete license agreement can be found here:
* http://opcfoundation.org/License/MIT/1.00/
* ======================================================================*/
using System;
using System.Globalization;
using Microsoft.Extensions.Logging;
using Opc.Ua.Security.Certificates;
namespace Opc.Ua.Server
{
///
/// An interface to report audit events in the server.
///
public interface IAuditEventServer
{
///
/// If auditing is enabled.
///
bool Auditing { get; }
///
/// The default system context for the audit events.
///
ISystemContext DefaultAuditContext { get; }
///
/// Called by any component to report an audit event.
///
/// The context.
/// The event.
void ReportAuditEvent(ISystemContext context, AuditEventState e);
}
///
/// The implementation of audit events.
///
public static class AuditEvents
{
///
/// Placeholder used in audit event InputArguments to indicate
/// a private key byte string has been redacted before the event was
/// raised. Used by UpdateCertificate per OPC 10000-12 §7.10.3
/// to avoid leaking private-key material into audit payloads.
///
public static readonly ByteString RedactedPrivateKey = ByteString.Empty;
///
/// Report Audit event
///
/// The server which reports audit events.
/// Client operation info
/// Audit method name
/// The service exception that includes also a status code
/// A contextual logger to log to
public static void ReportAuditEvent(
this IAuditEventServer? server,
OperationContext operationContext,
string methodName,
ServiceResultException serviceResultException,
ILogger logger)
{
if (server?.Auditing != true)
{
// current server does not support auditing
return;
}
try
{
ISystemContext systemContext = server.DefaultAuditContext;
var e = new AuditEventState(null);
var message = new TranslationInfo(
"AuditEvent",
"en-US",
$"Method {methodName} failed. Result: {serviceResultException.Message}.");
e.Initialize(
systemContext,
null,
EventSeverity.Min,
new LocalizedText(message),
StatusCode.IsGood(serviceResultException.StatusCode),
DateTime.UtcNow
); // initializes Status, ActionTimeStamp, ServerId, ClientAuditEntryId, ClientUserId
e.SetChildValue(systemContext, BrowseNames.SourceNode, ObjectIds.Server, false);
e.SetChildValue(
systemContext,
BrowseNames.SourceName,
$"Attribute/{methodName}",
false);
e.SetChildValue(
systemContext,
BrowseNames.LocalTime,
TimeZoneDataType.Local,
false);
e.SetChildValue(
systemContext,
BrowseNames.ClientUserId,
operationContext?.UserIdentity?.DisplayName!,
false);
e.SetChildValue(
systemContext,
BrowseNames.ClientAuditEntryId,
operationContext?.AuditEntryId!,
false);
server.ReportAuditEvent(systemContext, e);
}
catch (Exception ex)
{
logger.LogError(ex, "Error while reporting AuditEvent event.");
}
}
///
/// Reports an AuditWriteUpdate event.
///
/// The server which reports audit events.
/// The current system context.
/// The value to write.
/// The old value of the node.
/// The resulted status code.
/// A contextual logger to log to
public static void ReportAuditWriteUpdateEvent(
this IAuditEventServer? server,
ISystemContext systemContext,
WriteValue writeValue,
Variant oldValue,
StatusCode statusCode,
ILogger logger)
{
if (server?.Auditing != true)
{
// current server does not support auditing
return;
}
if (systemContext is not ISessionSystemContext session ||
session.UserIdentity == null)
{
return;
}
try
{
var e = new AuditWriteUpdateEventState(null);
var message = new TranslationInfo(
"AuditWriteUpdateEvent",
"en-US",
"AuditWriteUpdateEvent.");
e.Initialize(
systemContext,
null,
EventSeverity.Min,
new LocalizedText(message),
StatusCode.IsGood(statusCode),
DateTime.UtcNow
); // initializes Status, ActionTimeStamp, ServerId, ClientAuditEntryId, ClientUserId
e.SetChildValue(systemContext, BrowseNames.SourceNode, writeValue.NodeId, false);
e.SetChildValue(systemContext, BrowseNames.SourceName, "Attribute/Write", false);
e.SetChildValue(
systemContext,
BrowseNames.LocalTime,
TimeZoneDataType.Local,
false);
e.SetChildValue(
systemContext,
BrowseNames.ClientUserId,
session.UserIdentity.DisplayName,
false);
e.SetChildValue(
systemContext,
BrowseNames.ClientAuditEntryId,
systemContext.AuditEntryId!,
false);
e.SetChildValue(
systemContext,
BrowseNames.AttributeId,
writeValue.AttributeId,
false);
e.SetChildValue(
systemContext,
BrowseNames.IndexRange,
writeValue.IndexRange!,
false);
Variant newValue;
if (!writeValue.ParsedIndexRange.IsNull)
{
newValue = oldValue;
writeValue.ParsedIndexRange.UpdateRange(
ref newValue,
writeValue.Value.WrappedValue);
}
else
{
newValue = writeValue.Value.WrappedValue;
}
e.SetChildValue(systemContext, BrowseNames.NewValue, newValue, false);
e.SetChildValue(systemContext, BrowseNames.OldValue, oldValue, false);
server.ReportAuditEvent(systemContext, e);
}
catch (Exception ex)
{
logger.LogError(ex, "Error while reporting AuditWriteUpdateEvent event.");
}
}
///
/// Reports an AuditHistoryValueUpdate event.
///
/// The server which reports audit events.
/// The current system context.
/// Update data details
/// The old values
/// The resulting status code
/// A contextual logger to log to
public static void ReportAuditHistoryValueUpdateEvent(
this IAuditEventServer? server,
ISystemContext systemContext,
UpdateDataDetails updateDataDetails,
DataValue[] oldValues,
StatusCode statusCode,
ILogger logger)
{
if (server?.Auditing != true)
{
// current server does not support auditing
return;
}
try
{
var e = new AuditHistoryValueUpdateEventState(null);
InitializeAuditHistoryUpdateEvent(
e,
systemContext,
"AuditHistoryValueUpdateEvent",
"Attribute/HistoryValueUpdate",
updateDataDetails,
statusCode);
e.SetChildValue(
systemContext,
BrowseNames.UpdatedNode,
updateDataDetails.NodeId,
false);
e.SetChildValue(
systemContext,
BrowseNames.PerformInsertReplace,
updateDataDetails.PerformInsertReplace);
e.SetChildValue(
systemContext,
BrowseNames.NewValues,
updateDataDetails.UpdateValues,
false);
e.SetChildValue(systemContext, BrowseNames.OldValues, oldValues.ToArrayOf(), false);
server.ReportAuditEvent(systemContext, e);
}
catch (Exception ex)
{
logger.LogError(ex, "Error while reporting AuditHistoryValueUpdateEvent event.");
}
}
///
/// Reports an AuditHistoryValueUpdate event.
///
/// The server which reports audit events.
/// The current system context.
/// Update structure data details
/// The old values
/// The resulting status code
/// A contextual logger to log to
public static void ReportAuditHistoryAnnotationUpdateEvent(
this IAuditEventServer? server,
ISystemContext systemContext,
UpdateStructureDataDetails updateStructureDataDetails,
ArrayOf oldValues,
StatusCode statusCode,
ILogger logger)
{
if (server?.Auditing != true)
{
// current server does not support auditing
return;
}
try
{
var e = new AuditHistoryAnnotationUpdateEventState(null);
InitializeAuditHistoryUpdateEvent(
e,
systemContext,
"AuditHistoryAnnotationUpdateEvent",
"Attribute/HistoryAnnotationUpdate",
updateStructureDataDetails,
statusCode);
e.SetChildValue(
systemContext,
BrowseNames.PerformInsertReplace,
updateStructureDataDetails.PerformInsertReplace);
e.SetChildValue(
systemContext,
BrowseNames.NewValues,
updateStructureDataDetails.UpdateValues,
false);
e.SetChildValue(systemContext, BrowseNames.OldValues, oldValues, false);
server.ReportAuditEvent(systemContext, e);
}
catch (Exception ex)
{
logger.LogError(ex, "Error while reporting AuditHistoryValueUpdateEvent event.");
}
}
///
/// Reports an AuditHistoryEventUpdate event.
///
/// The server which reports audit events.
/// The current system context.
/// Update event details
/// The old values
/// The resulting status code
/// A contextual logger to log to
public static void ReportAuditHistoryEventUpdateEvent(
this IAuditEventServer? server,
ISystemContext systemContext,
UpdateEventDetails updateEventDetails,
ArrayOf oldValues,
StatusCode statusCode,
ILogger logger)
{
if (server?.Auditing != true)
{
// current server does not support auditing
return;
}
try
{
var e = new AuditHistoryEventUpdateEventState(null);
InitializeAuditHistoryUpdateEvent(
e,
systemContext,
"AuditHistoryEventUpdateEvent",
"Attribute/HistoryEventUpdate",
updateEventDetails,
statusCode);
e.SetChildValue(
systemContext,
BrowseNames.UpdatedNode,
updateEventDetails.NodeId,
false);
e.SetChildValue(
systemContext,
BrowseNames.PerformInsertReplace,
updateEventDetails.PerformInsertReplace);
e.SetChildValue(
systemContext,
BrowseNames.Filter,
updateEventDetails.Filter,
false);
e.SetChildValue(
systemContext,
BrowseNames.NewValues,
updateEventDetails.EventData,
false);
e.SetChildValue(systemContext, BrowseNames.OldValues, oldValues, false);
server.ReportAuditEvent(systemContext, e);
}
catch (Exception ex)
{
logger.LogError(ex, "Error while reporting AuditHistoryEventUpdateEvent event.");
}
}
///
/// Reports an AuditHistoryRawModifyDelete event.
///
/// The server which reports audit events.
/// The current system context.
/// History raw modified details
/// The old values
/// The resulting status code
/// A contextual logger to log to
public static void ReportAuditHistoryRawModifyDeleteEvent(
this IAuditEventServer? server,
ISystemContext systemContext,
DeleteRawModifiedDetails deleteRawModifiedDetails,
ArrayOf oldValues,
StatusCode statusCode,
ILogger logger)
{
if (server?.Auditing != true)
{
// current server does not support auditing
return;
}
try
{
var e = new AuditHistoryRawModifyDeleteEventState(null);
InitializeAuditHistoryUpdateEvent(
e,
systemContext,
"AuditHistoryRawModifyDeleteEvent",
"Attribute/HistoryRawModifyDelete",
deleteRawModifiedDetails,
statusCode);
e.SetChildValue(
systemContext,
BrowseNames.UpdatedNode,
deleteRawModifiedDetails.NodeId,
false);
e.SetChildValue(
systemContext,
BrowseNames.IsDeleteModified,
deleteRawModifiedDetails.IsDeleteModified,
false);
e.SetChildValue(
systemContext,
BrowseNames.StartTime,
deleteRawModifiedDetails.StartTime,
false);
e.SetChildValue(
systemContext,
BrowseNames.EndTime,
deleteRawModifiedDetails.EndTime,
false);
e.SetChildValue(systemContext, BrowseNames.OldValues, oldValues, false);
server.ReportAuditEvent(systemContext, e);
}
catch (Exception ex)
{
logger.LogError(ex, "Error while reporting AuditHistoryRawModifyDeleteEvent event.");
}
}
///
/// Reports an AuditHistoryAtTimeDelete event.
///
/// The server which reports audit events.
/// The current system context.
/// History delete at time details
/// The old values
/// The resulting status code
/// A contextual logger to log to
public static void ReportAuditHistoryAtTimeDeleteEvent(
this IAuditEventServer? server,
ISystemContext systemContext,
DeleteAtTimeDetails deleteAtTimeDetails,
DataValue[] oldValues,
StatusCode statusCode,
ILogger logger)
{
if (server?.Auditing != true)
{
// current server does not support auditing
return;
}
try
{
var e = new AuditHistoryAtTimeDeleteEventState(null);
InitializeAuditHistoryUpdateEvent(
e,
systemContext,
"AuditHistoryAtTimeDeleteEvent",
"Attribute/HistoryAtTimeDelete",
deleteAtTimeDetails,
statusCode);
e.SetChildValue(
systemContext,
BrowseNames.UpdatedNode,
deleteAtTimeDetails.NodeId,
false);
e.SetChildValue(
systemContext,
BrowseNames.ReqTimes,
deleteAtTimeDetails.ReqTimes,
false);
e.SetChildValue(systemContext, BrowseNames.OldValues, Variant.From(oldValues), false);
server.ReportAuditEvent(systemContext, e);
}
catch (Exception ex)
{
logger.LogError(ex, "Error while reporting AuditHistoryAtTimeDeleteEvent event.");
}
}
///
/// Reports an AuditHistoryEventDelete event.
///
/// The server which reports audit events.
/// The current system context.
/// History delete event details
/// The old values
/// The resulting status code
/// A contextual logger to log to
public static void ReportAuditHistoryEventDeleteEvent(
this IAuditEventServer? server,
ISystemContext systemContext,
DeleteEventDetails deleteEventDetails,
DataValue[] oldValues,
StatusCode statusCode,
ILogger logger)
{
if (server?.Auditing != true)
{
// current server does not support auditing
return;
}
try
{
var e = new AuditHistoryEventDeleteEventState(null);
InitializeAuditHistoryUpdateEvent(
e,
systemContext,
"AuditHistoryEventDeleteEvent",
"Attribute/HistoryEventDelete",
deleteEventDetails,
statusCode);
e.SetChildValue(
systemContext,
BrowseNames.UpdatedNode,
deleteEventDetails.NodeId,
false);
e.SetChildValue(
systemContext,
BrowseNames.EventIds,
Variant.From(deleteEventDetails.EventIds),
false);
e.SetChildValue(systemContext, BrowseNames.OldValues, Variant.From(oldValues), false);
server.ReportAuditEvent(systemContext, e);
}
catch (Exception ex)
{
logger.LogError(ex, "Error while reporting AuditHistoryEventDeleteEvent event.");
}
}
///
/// Reports all audit events for client certificate ServiceResultException.
/// It goes recursively for all service results stored in the exception
///
/// The server which reports audit events.
/// The client certificate.
/// The Exception that triggers a certificate audit event.
/// A contextual logger to log to
public static void ReportAuditCertificateEvent(
this IAuditEventServer? server,
Certificate clientCertificate,
Exception? exception,
ILogger logger)
{
if (exception == null)
{
return;
}
if (server?.Auditing != true)
{
// current server does not support auditing
return;
}
try
{
ISystemContext systemContext = server.DefaultAuditContext;
while (exception != null)
{
if (exception is ServiceResultException sre && sre.InnerResult != null)
{
// Each validation step has a unique error status and audit event type
// that shall be reported if the check fails.
server.ReportAuditCertificateEvent(logger, systemContext, clientCertificate, sre);
}
exception = exception.InnerException;
}
}
catch (Exception ex)
{
logger.LogError(
ex,
"Error while reporting ReportAuditCertificateDataMismatch event.");
}
}
///
/// Report the audit certificate event for the specified ServiceResultException
///
private static void ReportAuditCertificateEvent(
this IAuditEventServer server,
ILogger logger,
ISystemContext systemContext,
Certificate clientCertificate,
ServiceResultException sre)
{
try
{
if (StatusCode.IsBad(sre!.InnerResult!.Code))
{
AuditCertificateEventState auditCertificateEventState;
if (sre.StatusCode == StatusCodes.BadCertificateTimeInvalid ||
sre.StatusCode == StatusCodes.BadCertificateIssuerTimeInvalid)
{
// create AuditCertificateExpiredEventType
auditCertificateEventState = new AuditCertificateExpiredEventState(
null);
}
else if (sre.StatusCode == StatusCodes.BadCertificateInvalid ||
sre.StatusCode == StatusCodes.BadCertificateChainIncomplete ||
sre.StatusCode == StatusCodes.BadCertificatePolicyCheckFailed)
{
// create AuditCertificateInvalidEventType
auditCertificateEventState = new AuditCertificateInvalidEventState(
null);
}
else if (sre.StatusCode == StatusCodes.BadCertificateUntrusted)
{
// create AuditCertificateUntrustedEventType
auditCertificateEventState = new AuditCertificateUntrustedEventState(
null);
}
else if (sre.StatusCode == StatusCodes.BadCertificateRevoked ||
sre.StatusCode == StatusCodes.BadCertificateIssuerRevoked ||
sre.StatusCode == StatusCodes.BadCertificateRevocationUnknown)
{
// create AuditCertificateRevokedEventType
auditCertificateEventState = new AuditCertificateRevokedEventState(
null);
}
else if (sre.StatusCode == StatusCodes.BadCertificateUseNotAllowed ||
sre.StatusCode == StatusCodes.BadCertificateIssuerUseNotAllowed)
{
// create AuditCertificateMismatchEventType
auditCertificateEventState = new AuditCertificateMismatchEventState(
null);
}
else
{
return;
}
auditCertificateEventState.Initialize(
systemContext,
null,
EventSeverity.Min,
LocalizedText.From(sre.Message),
false,
DateTime.UtcNow
); // initializes Status, ActionTimeStamp, ServerId, ClientAuditEntryId, ClientUserId
auditCertificateEventState.SetChildValue(
systemContext,
BrowseNames.SourceName,
"Security/Certificate",
false);
// set AuditSecurityEventType fields
auditCertificateEventState.SetChildValue(
systemContext,
BrowseNames.StatusCodeId,
sre.InnerResult.StatusCode,
false);
// set AuditCertificateEventType fields
auditCertificateEventState.SetChildValue(
systemContext,
BrowseNames.Certificate,
clientCertificate?.RawData.ToByteString() ?? default,
false);
server.ReportAuditEvent(systemContext, auditCertificateEventState);
}
}
catch (Exception ex)
{
logger.LogError(
ex,
"Error while reporting ReportAuditCertificateDataMismatch event.");
}
}
///
/// Reports the AuditCertificateDataMismatchEventType for Invalid Uri
///
/// The server which reports audit events.
/// The client certificate
/// The string that represents the host name passed in as
/// part of the URL that is found to be invalid. If the host name was not invalid it can be null.
/// The URI that was passed in and found to not match what is
/// contained in the certificate. If the URI was not invalid it can be null.
/// The status code.
/// A contextual logger to log to
public static void ReportAuditCertificateDataMismatchEvent(
this IAuditEventServer? server,
Certificate clientCertificate,
string? invalidHostName,
string? invalidUri,
StatusCode statusCode,
ILogger logger)
{
if (server?.Auditing != true)
{
// current server does not support auditing
return;
}
try
{
ISystemContext systemContext = server.DefaultAuditContext;
// create AuditCertificateDataMismatchEventType
var e = new AuditCertificateDataMismatchEventState(null);
e.Initialize(
systemContext,
null,
EventSeverity.Min,
default,
StatusCode.IsGood(statusCode),
DateTime.UtcNow
); // initializes Status, ActionTimeStamp, ServerId, ClientAuditEntryId, ClientUserId
e.SetChildValue(
systemContext,
BrowseNames.SourceName,
"Security/Certificate",
false);
e.SetChildValue(systemContext, BrowseNames.SourceNode, ObjectIds.Server, false);
e.SetChildValue(
systemContext,
BrowseNames.LocalTime,
TimeZoneDataType.Local,
false);
// set AuditSecurityEventType fields
e.SetChildValue(systemContext, BrowseNames.StatusCodeId, statusCode, false);
// set AuditCertificateEventType fields
e.SetChildValue(
systemContext,
BrowseNames.Certificate,
Variant.From(ByteString.From(clientCertificate?.RawData)),
false);
// set AuditCertificateDataMismatchEventState fields
e.SetChildValue(systemContext, BrowseNames.InvalidUri, invalidUri!, false);
e.SetChildValue(systemContext, BrowseNames.InvalidHostname, invalidHostName!, false);
server.ReportAuditEvent(systemContext, e);
}
catch (Exception ex)
{
logger.LogError(
ex,
"Error while reporting ReportAuditCertificateDataMismatchEvent event.");
}
}
///
/// Report the AuditCancelEventState
///
/// The server which reports audit events.
/// Session id of the current session
/// The handle of the canceled request
/// The resulted status code of cancel request.
/// A contextual logger to log to
public static void ReportAuditCancelEvent(
this IAuditEventServer? server,
NodeId sessionId,
uint requestHandle,
StatusCode statusCode,
ILogger logger)
{
if (server?.Auditing != true)
{
// current server does not support auditing
return;
}
try
{
ISystemContext systemContext = server.DefaultAuditContext;
// create AuditCancelEventState
var e = new AuditCancelEventState(null);
e.Initialize(
systemContext,
null,
EventSeverity.Min,
LocalizedText.From($"Cancel requested for sessionId: {sessionId} with requestHandle: {requestHandle}"),
StatusCode.IsGood(statusCode),
DateTime.UtcNow
); // initializes Status, ActionTimeStamp, ServerId, ClientAuditEntryId, ClientUserId
e.SetChildValue(systemContext, BrowseNames.SourceName, "Session/Cancel", false);
e.SetChildValue(systemContext, BrowseNames.SourceNode, ObjectIds.Server, false);
e.SetChildValue(
systemContext,
BrowseNames.LocalTime,
TimeZoneDataType.Local,
false);
// set AuditSecurityEventType fields
e.SetChildValue(systemContext, BrowseNames.StatusCodeId, statusCode, false);
// set AuditSessionEventType fields
e.SetChildValue(systemContext, BrowseNames.SessionId, sessionId, false);
// set AuditCancelEventType fields
e.SetChildValue(systemContext, BrowseNames.RequestHandle, requestHandle, false);
server.ReportAuditEvent(systemContext, e);
}
catch (Exception ex)
{
logger.LogError(ex, "Error while reporting ReportAuditCancelEvent event.");
}
}
///
/// Reports a RoleMappingRuleChangedAuditEvent when a method is called on a RoleType instance
///
/// The server which reports audit events.
/// The current system context.
/// Role
/// The method
/// method arguments
/// Status of call
/// A contextual logger to log to
public static void ReportAuditRoleMappingRuleChangedEvent(
this IAuditEventServer? server,
ISystemContext systemContext,
NodeId roleStateObjectId,
MethodState method,
ArrayOf inputArguments,
bool status,
ILogger logger)
{
if (server?.Auditing != true)
{
// current server does not support auditing
return;
}
try
{
// create RoleMappingRuleChangedAuditEventState
var e = new RoleMappingRuleChangedAuditEventState(null);
e.Initialize(
systemContext,
null,
EventSeverity.Min,
LocalizedText.From($"RoleMappingRuleChanged - {method?.BrowseName}"),
status,
DateTime.UtcNow
); // initializes Status, ActionTimeStamp, ServerId, ClientAuditEntryId, ClientUserId
e.SetChildValue(systemContext, BrowseNames.SourceName, "Attribute/Call", false);
e.SetChildValue(systemContext, BrowseNames.SourceNode, roleStateObjectId, false);
e.SetChildValue(
systemContext,
BrowseNames.LocalTime,
TimeZoneDataType.Local,
false);
// set AuditUpdateMethodEventType fields
e.SetChildValue(systemContext, BrowseNames.MethodId, method?.NodeId ?? default, false);
e.SetChildValue(systemContext, BrowseNames.InputArguments, inputArguments, false);
server.ReportAuditEvent(systemContext, e);
}
catch (Exception ex)
{
logger.LogError(
ex,
"Error while reporting ReportRoleMappingRuleChangedAuditEvent event.");
}
}
///
/// Reports an audit create session event.
///
/// The server which reports audit events.
/// The audit entry id.
/// The session object that was created.
/// The revised session timeout
/// A contextual logger to log to
/// The exception received during create session request
public static void ReportAuditCreateSessionEvent(
this IAuditEventServer? server,
string auditEntryId,
ISession session,
double revisedSessionTimeout,
ILogger logger,
Exception? exception = null)
{
if (server?.Auditing != true)
{
// current server does not support auditing
return;
}
try
{
ISystemContext systemContext = server.DefaultAuditContext;
// raise an audit event.
var e = new AuditCreateSessionEventState(null);
TranslationInfo message = default;
if (exception == null)
{
message = new TranslationInfo(
"AuditCreateSessionEvent",
"en-US",
$"Session with ID:{session?.Id} was created.");
}
else
{
message = new TranslationInfo(
"AuditCreateSessionEvent",
"en-US",
$"Error while creating session with ID:{session?.Id}: Exception: {exception.Message}.");
}
InitializeAuditSessionEvent(
systemContext,
e,
message,
exception == null,
session!,
auditEntryId);
e.SetChildValue(
systemContext,
BrowseNames.ClientUserId,
"System/CreateSession",
false);
e.SetChildValue(
systemContext,
BrowseNames.SourceName,
"Session/CreateSession",
false);
// set AuditCreateSessionEventState fields
e.SetChildValue(
systemContext,
BrowseNames.ClientCertificate,
ByteString.From(session?.ClientCertificate?.RawData),
false);
e.SetChildValue(
systemContext,
BrowseNames.ClientCertificateThumbprint,
session?.ClientCertificate?.Thumbprint!,
false);
e.SetChildValue(
systemContext,
BrowseNames.RevisedSessionTimeout,
revisedSessionTimeout,
false);
server.ReportAuditEvent(systemContext, e);
}
catch (Exception ex)
{
logger.LogError(
ex,
"Error while reporting AuditCreateSessionEvent event for SessionId {SessionId}.",
session?.Id);
}
}
///
/// Reports an audit activate session event.
///
/// The server which reports audit events.
/// A contextual logger to log to
/// The audit entry id.
/// The session that is activated.
/// The exception received during activate session request
public static void ReportAuditActivateSessionEvent(
this IAuditEventServer? server,
ILogger logger,
string auditEntryId,
ISession session,
Exception? exception = null)
{
if (server?.Auditing != true)
{
// current server does not support auditing
return;
}
try
{
ISystemContext systemContext = server.DefaultAuditContext;
var e = new AuditActivateSessionEventState(null);
TranslationInfo message = default;
if (exception == null)
{
message = new TranslationInfo(
"AuditActivateSessionEvent",
"en-US",
$"Session with Id:{session?.Id} was activated.");
}
else
{
message = new TranslationInfo(
"AuditActivateSessionEvent",
"en-US",
$"Error while activate session with ID:{session?.Id}. Exception: {exception.Message}.");
}
InitializeAuditSessionEvent(
systemContext,
e,
message,
exception == null,
session!,
auditEntryId);
e.SetChildValue(
systemContext,
BrowseNames.SourceName,
"Session/ActivateSession",
false);
e.SetChildValue(
systemContext,
BrowseNames.UserIdentityToken,
CoreUtils.Clone(session?.IdentityToken?.Token)!,
false);
server.ReportAuditEvent(systemContext, e);
}
catch (Exception e)
{
logger.LogError(
e,
"Error while reporting AuditActivateSessionEvent event for SessionId {SessionId}.",
session?.Id);
}
}
///
/// Reports an audit Url Mismatch event.
///
/// The server which reports audit events.
/// The audit entry id.
/// The session object that was created.
/// The revised session timeout
/// The invalid endpoint url
/// A contextual logger to log to
public static void ReportAuditUrlMismatchEvent(
this IAuditEventServer? server,
string auditEntryId,
ISession session,
double revisedSessionTimeout,
string endpointUrl,
ILogger logger)
{
if (server?.Auditing != true)
{
// current server does not support auditing
return;
}
try
{
ISystemContext systemContext = server.DefaultAuditContext;
var e = new AuditUrlMismatchEventState(null);
var message = new TranslationInfo(
"AuditUrlMismatchEvent",
"en-US",
$"Session with ID:{session.Id} was created but the endpoint URL does not match the domain names in the server certificate.");
InitializeAuditSessionEvent(
systemContext,
e,
message,
false,
session,
auditEntryId);
e.SetChildValue(
systemContext,
BrowseNames.ClientUserId,
"System/CreateSession",
false);
e.SetChildValue(
systemContext,
BrowseNames.SourceName,
"Session/CreateSession",
false);
// set AuditCreateSessionEventState fields
e.SetChildValue(
systemContext,
BrowseNames.ClientCertificate,
ByteString.From(session?.ClientCertificate?.RawData),
false);
e.SetChildValue(
systemContext,
BrowseNames.ClientCertificateThumbprint,
session?.ClientCertificate?.Thumbprint!,
false);
e.SetChildValue(
systemContext,
BrowseNames.RevisedSessionTimeout,
revisedSessionTimeout,
false);
// set AuditUrlMismatchEventState
e.SetChildValue(systemContext, BrowseNames.EndpointUrl, endpointUrl, false);
server.ReportAuditEvent(systemContext, e);
}
catch (Exception e)
{
logger.LogError(
e,
"Error while reporting AuditUrlMismatchEvent event for SessionId {SessionId}.",
session?.Id);
}
}
///
/// Reports an audit close session event.
///
/// The server which reports audit events.
/// The audit entry id.
/// The session object that was created.
/// A contextual logger to log to
/// Session/CloseSession when the session is closed by request
/// “Session/Timeout” for a Session timeout
/// “Session/Terminated” for all other cases.
public static void ReportAuditCloseSessionEvent(
this IAuditEventServer? server,
string auditEntryId,
ISession session,
ILogger logger,
string sourceName = "Session/Terminated")
{
if (server?.Auditing != true)
{
// current server does not support auditing
return;
}
try
{
ISystemContext systemContext = server.DefaultAuditContext;
// raise an audit event.
var e = new AuditSessionEventState(null);
var message = new TranslationInfo(
"AuditCloseSessionEvent",
"en-US",
$"Session with ID:{session?.Id} was closed.");
InitializeAuditSessionEvent(systemContext, e, message, true, session!, auditEntryId);
e.SetChildValue(systemContext, BrowseNames.SourceName, sourceName, false);
server.ReportAuditEvent(systemContext, e);
}
catch (Exception ex)
{
logger.LogError(
ex,
"Error while reporting AuditSessionEventState close event for SessionId {SessionId}.",
session?.Id);
}
}
///
/// Reports an audit session event for the transfer subscription.
///
/// The server which reports audit events.
/// The audit entry id.
/// The session object that was created.
/// The status code resulting .
/// A contextual logger to log to
public static void ReportAuditTransferSubscriptionEvent(
this IAuditEventServer? server,
string auditEntryId,
ISession session,
StatusCode statusCode,
ILogger logger)
{
if (server?.Auditing != true)
{
// current server does not support auditing
return;
}
try
{
ISystemContext systemContext = server.DefaultAuditContext;
// raise an audit event.
var e = new AuditSessionEventState(null);
var message = new TranslationInfo(
"AuditSessionEventState",
"en-US",
$"Transfer subscription for session ID:{session?.Id} has statusCode {statusCode}.");
InitializeAuditSessionEvent(
systemContext,
e,
message,
StatusCode.IsGood(statusCode),
session!,
auditEntryId);
e.SetChildValue(systemContext, BrowseNames.SourceNode, session!.Id, false);
e.SetChildValue(
systemContext,
BrowseNames.SourceName,
"Session/TransferSubscriptions",
false);
server.ReportAuditEvent(systemContext, e);
}
catch (Exception ex)
{
logger.LogError(
ex,
"Error while reporting AuditSessionEventState close event for SessionId {SessionId}.",
session?.Id);
}
}
///
/// Raise CertificateUpdatedAudit event
///
/// The server which reports audit events.
/// The current system context.
/// The id of the object used for update certificate method
/// The method that triggered the audit event.
/// The input arguments used to call the method that triggered the audit event.
/// The id of the certificate group
/// the certificate type id
/// A contextual logger to log to
/// The exception resulted after executing the UpdateCertificate method. If null, the operation was successfull.
public static void ReportCertificateUpdatedAuditEvent(
this IAuditEventServer? server,
ISystemContext systemContext,
NodeId objectId,
MethodState method,
ArrayOf inputArguments,
NodeId certificateGroupId,
NodeId certificateTypeId,
ILogger logger,
Exception? exception = null)
{
try
{
var e = new CertificateUpdatedAuditEventState(null);
TranslationInfo message = default;
if (exception == null)
{
message = new TranslationInfo(
"CertificateUpdatedAuditEvent",
"en-US",
"CertificateUpdatedAuditEvent.");
}
else
{
message = new TranslationInfo(
"CertificateUpdatedAuditEvent",
"en-US",
$"CertificateUpdatedAuditEvent - Exception: {exception.Message}.");
}
e.Initialize(
systemContext,
null,
EventSeverity.Min,
new LocalizedText(message),
exception == null,
DateTime.UtcNow
); // initializes Status, ActionTimeStamp, ServerId, ClientAuditEntryId, ClientUserId
e.SetChildValue(systemContext, BrowseNames.SourceNode, objectId, false);
e.SetChildValue(
systemContext,
BrowseNames.SourceName,
"Method/UpdateCertificate",
false);
e.SetChildValue(
systemContext,
BrowseNames.LocalTime,
TimeZoneDataType.Local,
false);
e.SetChildValue(systemContext, BrowseNames.MethodId, method.NodeId, false);
e.SetChildValue(systemContext, BrowseNames.InputArguments, inputArguments, false);
e.SetChildValue(
systemContext,
BrowseNames.CertificateGroup,
certificateGroupId,
false);
e.SetChildValue(
systemContext,
BrowseNames.CertificateType,
certificateTypeId,
false);
server!.ReportAuditEvent(systemContext, e);
}
catch (Exception ex)
{
logger.LogError(
ex,
"Error while reporting ReportCertificateUpdatedAuditEvent event.");
}
}
///
/// Raise CertificateUpdateRequestedAudit event.
///
/// The server which reports audit events.
/// The current system context.
/// The id of the object used for update certificate method
/// The method that triggered the audit event.
/// The input arguments used to call the method that triggered the audit event.
/// A contextual logger to log to
///
/// If non-null, indicates the UpdateCertificate operation failed;
/// the audit event is raised with Status=false and the
/// exception message is embedded in the localized text.
///
public static void ReportCertificateUpdateRequestedAuditEvent(
this IAuditEventServer? server,
ISystemContext systemContext,
NodeId objectId,
MethodState method,
ArrayOf inputArguments,
ILogger logger,
Exception? exception = null)
{
try
{
var e = new CertificateUpdateRequestedAuditEventState(null);
TranslationInfo message = exception == null
? new TranslationInfo(
"CertificateUpdateRequestedAuditEvent",
"en-US",
"CertificateUpdateRequestedAuditEvent.")
: new TranslationInfo(
"CertificateUpdateRequestedAuditEvent",
"en-US",
$"CertificateUpdateRequestedAuditEvent - Exception: {exception.Message}.");
e.Initialize(
systemContext,
null,
EventSeverity.Min,
new LocalizedText(message),
exception == null,
DateTime.UtcNow); // initializes Status, ActionTimeStamp, ServerId, ClientAuditEntryId, ClientUserId
e.SetChildValue(systemContext, BrowseNames.SourceNode, objectId, false);
e.SetChildValue(
systemContext,
BrowseNames.SourceName,
"Method/UpdateCertificate",
false);
e.SetChildValue(
systemContext,
BrowseNames.LocalTime,
TimeZoneDataType.Local,
false);
e.SetChildValue(systemContext, BrowseNames.MethodId, method?.NodeId ?? default, false);
e.SetChildValue(systemContext, BrowseNames.InputArguments, inputArguments, false);
server?.ReportAuditEvent(systemContext, e);
}
catch (Exception ex)
{
logger.LogError(
ex,
"Error while reporting CertificateUpdateRequestedAuditEvent event.");
}
}
///
/// Report the AuditAddNodesEvent
///
/// The server which reports audit events.
/// The current system context.
/// The added nodes information.
/// Custom message for add nodes audit event.
/// The resulting status code.
/// A contextual logger to log to
public static void ReportAuditAddNodesEvent(
this IAuditEventServer? server,
ISystemContext systemContext,
ArrayOf addNodesItems,
string customMessage,
StatusCode statusCode,
ILogger logger)
{
if (server?.Auditing != true)
{
// current server does not support auditing
return;
}
try
{
var e = new AuditAddNodesEventState(null);
var message = new TranslationInfo(
"AuditAddNodesEventState",
"en-US",
$"'{customMessage}' returns StatusCode: {statusCode.ToString(null, CultureInfo.InvariantCulture)}.");
e.Initialize(
systemContext,
null,
EventSeverity.Min,
new LocalizedText(message),
StatusCode.IsGood(statusCode),
DateTime.UtcNow
); // initializes Status, ActionTimeStamp, ServerId, ClientAuditEntryId, ClientUserId
e.SetChildValue(systemContext, BrowseNames.SourceNode, ObjectIds.Server, false);
e.SetChildValue(
systemContext,
BrowseNames.SourceName,
"NodeManagement/AddNodes",
false);
e.SetChildValue(
systemContext,
BrowseNames.LocalTime,
TimeZoneDataType.Local,
false);
e.SetChildValue(systemContext, BrowseNames.NodesToAdd, addNodesItems, false);
server.ReportAuditEvent(systemContext, e);
}
catch (Exception ex)
{
logger.LogError(ex, "Error while reporting AuditAddNodesEvent event.");
}
}
///
/// Reports the AuditDeleteNodesEvent.
///
/// The server which reports audit events.
/// The current system context.
/// The delete nodes information.
/// Custom message for delete nodes.
/// The resulting status code.
/// A contextual logger to log to
public static void ReportAuditDeleteNodesEvent(
this IAuditEventServer? server,
ISystemContext systemContext,
ArrayOf nodesToDelete,
string customMessage,
StatusCode statusCode,
ILogger logger)
{
if (server?.Auditing != true)
{
// current server does not support auditing
return;
}
try
{
var e = new AuditDeleteNodesEventState(null);
var message = new TranslationInfo(
"AuditDeleteNodesEventState",
"en-US",
$"'{customMessage}' returns StatusCode: {statusCode.ToString(null, CultureInfo.InvariantCulture)}.");
e.Initialize(
systemContext,
null,
EventSeverity.Min,
new LocalizedText(message),
StatusCode.IsGood(statusCode),
DateTime.UtcNow
); // initializes Status, ActionTimeStamp, ServerId, ClientAuditEntryId, ClientUserId
e.SetChildValue(systemContext, BrowseNames.SourceNode, ObjectIds.Server, false);
e.SetChildValue(
systemContext,
BrowseNames.SourceName,
"NodeManagement/DeleteNodes",
false);
e.SetChildValue(
systemContext,
BrowseNames.LocalTime,
TimeZoneDataType.Local,
false);
e.SetChildValue(systemContext, BrowseNames.NodesToDelete, nodesToDelete, false);
server.ReportAuditEvent(systemContext, e);
}
catch (Exception ex)
{
logger.LogError(ex, "Error while reporting AuditDeleteNodesEvent event.");
}
}
///
/// Reports the AuditAddReferencesEvent.
///
/// The server which reports audit events.
/// The current system context.
/// The references being added.
/// Custom message for the audit event.
/// The resulting status code.
/// A contextual logger to log to
public static void ReportAuditAddReferencesEvent(
this IAuditEventServer? server,
ISystemContext systemContext,
ArrayOf referencesToAdd,
string customMessage,
StatusCode statusCode,
ILogger logger)
{
if (server?.Auditing != true)
{
return;
}
try
{
var e = new AuditAddReferencesEventState(null);
var message = new TranslationInfo(
"AuditAddReferencesEventState",
"en-US",
$"'{customMessage}' returns StatusCode: {statusCode.ToString(null, CultureInfo.InvariantCulture)}.");
e.Initialize(
systemContext,
null,
EventSeverity.Min,
new LocalizedText(message),
StatusCode.IsGood(statusCode),
DateTime.UtcNow
);
e.SetChildValue(systemContext, BrowseNames.SourceNode, ObjectIds.Server, false);
e.SetChildValue(
systemContext,
BrowseNames.SourceName,
"NodeManagement/AddReferences",
false);
e.SetChildValue(
systemContext,
BrowseNames.LocalTime,
TimeZoneDataType.Local,
false);
e.SetChildValue(systemContext, BrowseNames.ReferencesToAdd, referencesToAdd, false);
server.ReportAuditEvent(systemContext, e);
}
catch (Exception ex)
{
logger.LogError(ex, "Error while reporting AuditAddReferencesEvent event.");
}
}
///
/// Reports the AuditDeleteReferencesEvent.
///
/// The server which reports audit events.
/// The current system context.
/// The references being deleted.
/// Custom message for the audit event.
/// The resulting status code.
/// A contextual logger to log to
public static void ReportAuditDeleteReferencesEvent(
this IAuditEventServer? server,
ISystemContext systemContext,
ArrayOf referencesToDelete,
string customMessage,
StatusCode statusCode,
ILogger logger)
{
if (server?.Auditing != true)
{
return;
}
try
{
var e = new AuditDeleteReferencesEventState(null);
var message = new TranslationInfo(
"AuditDeleteReferencesEventState",
"en-US",
$"'{customMessage}' returns StatusCode: {statusCode.ToString(null, CultureInfo.InvariantCulture)}.");
e.Initialize(
systemContext,
null,
EventSeverity.Min,
new LocalizedText(message),
StatusCode.IsGood(statusCode),
DateTime.UtcNow
);
e.SetChildValue(systemContext, BrowseNames.SourceNode, ObjectIds.Server, false);
e.SetChildValue(
systemContext,
BrowseNames.SourceName,
"NodeManagement/DeleteReferences",
false);
e.SetChildValue(
systemContext,
BrowseNames.LocalTime,
TimeZoneDataType.Local,
false);
e.SetChildValue(systemContext, BrowseNames.ReferencesToDelete, referencesToDelete, false);
server.ReportAuditEvent(systemContext, e);
}
catch (Exception ex)
{
logger.LogError(ex, "Error while reporting AuditDeleteReferencesEvent event.");
}
}
///
/// Report the open secure channel audit event.
///
/// The server which reports audit events.
/// The global unique channel id.
/// The endpoint description used for the request.
/// The incoming
/// The client certificate.
/// The exception resulted from the open secure channel request.
/// A contextual logger to log to
public static void ReportAuditOpenSecureChannelEvent(
this IAuditEventServer? server,
string globalChannelId,
EndpointDescription endpointDescription,
OpenSecureChannelRequest request,
Certificate clientCertificate,
Exception? exception,
ILogger logger)
{
if (server?.Auditing != true)
{
// current server does not support auditing
return;
}
try
{
// raise an audit event.
var e = new AuditOpenSecureChannelEventState(null);
TranslationInfo message = default;
if (exception == null)
{
message = new TranslationInfo(
"AuditOpenSecureChannelEvent",
"en-US",
"AuditOpenSecureChannelEvent");
}
else
{
message = new TranslationInfo(
"AuditOpenSecureChannelEvent",
"en-US",
$"AuditOpenSecureChannelEvent - Exception: {exception.Message}.");
}
StatusCode statusCode = StatusCodes.Good;
while (exception is not null and not ServiceResultException)
{
exception = exception.InnerException;
}
if (exception is ServiceResultException sre)
{
if (sre.InnerResult != null)
{
statusCode = sre.InnerResult.StatusCode;
}
else
{
statusCode = sre.StatusCode;
}
}
ISystemContext systemContext = server.DefaultAuditContext;
DateTime actionTimestamp = DateTime.UtcNow;
if (request?.RequestHeader?.Timestamp != null)
{
actionTimestamp = (DateTime)request.RequestHeader.Timestamp;
}
e.Initialize(
systemContext,
null,
EventSeverity.Min,
new LocalizedText(message),
exception == null,
actionTimestamp
); // initializes Status, ActionTimeStamp, ServerId, ClientUserId
e.SetChildValue(
systemContext,
BrowseNames.ClientAuditEntryId,
request?.RequestHeader?.AuditEntryId!,
false);
e.SetChildValue(
systemContext,
BrowseNames.SourceName,
"SecureChannel/OpenSecureChannel",
false);
e.SetChildValue(
systemContext,
BrowseNames.ClientUserId,
"System/OpenSecureChannel",
false);
e.SetChildValue(systemContext, BrowseNames.SourceNode, ObjectIds.Server, false);
e.SetChildValue(
systemContext,
BrowseNames.LocalTime,
TimeZoneDataType.Local,
false);
// set AuditSecurityEventType fields
e.SetChildValue(systemContext, BrowseNames.StatusCodeId, statusCode, false);
// set AuditChannelEventType fields
e.SetChildValue(systemContext, BrowseNames.SecureChannelId, globalChannelId, false);
if (clientCertificate != null)
{
// set AuditOpenSecureChannelEventType fields
e.SetChildValue(
systemContext,
BrowseNames.ClientCertificate,
clientCertificate.RawData.ToByteString(),
false);
e.SetChildValue(
systemContext,
BrowseNames.ClientCertificateThumbprint,
clientCertificate.Thumbprint,
false);
}
if (endpointDescription != null)
{
e.SetChildValue(
systemContext,
BrowseNames.SecurityPolicyUri,
endpointDescription.SecurityPolicyUri!,
false);
e.SetChildValue(
systemContext,
BrowseNames.SecurityMode,
endpointDescription.SecurityMode);
}
if (request != null)
{
e.SetChildValue(
systemContext,
BrowseNames.RequestType,
request.RequestType);
e.SetChildValue(
systemContext,
BrowseNames.RequestedLifetime,
request.RequestedLifetime,
false);
}
server.ReportAuditEvent(systemContext, e);
}
catch (Exception ex)
{
logger.LogError(ex, "Error while reporting AuditOpenSecureChannelEvent event.");
}
}
///
/// Report the close secure channel audit event.
///
/// The server which reports audit events.
/// The global unique channel id.
/// The exception resulted from the open secure channel request.
/// A contextual logger to log to
public static void ReportAuditCloseSecureChannelEvent(
this IAuditEventServer? server,
string globalChannelId,
Exception? exception,
ILogger logger)
{
if (server?.Auditing != true)
{
// current server does not support auditing
return;
}
try
{
// raise an audit event.
var e = new AuditChannelEventState(null);
TranslationInfo message = default;
if (exception == null)
{
message = new TranslationInfo(
"AuditCloseSecureChannelEvent",
"en-US",
"AuditCloseSecureChannelEvent");
}
else
{
message = new TranslationInfo(
"AuditCloseSecureChannelEvent",
"en-US",
$"AuditCloseSecureChannelEvent - Exception: {exception.Message}.");
}
StatusCode statusCode = StatusCodes.Good;
while (exception is not null and not ServiceResultException)
{
exception = exception.InnerException;
}
if (exception is ServiceResultException sre)
{
statusCode = sre.InnerResult?.StatusCode ?? StatusCodes.Uncertain;
}
ISystemContext systemContext = server.DefaultAuditContext;
e.Initialize(
systemContext,
null,
EventSeverity.Min,
new LocalizedText(message),
exception == null,
DateTime.UtcNow
); // initializes Status, ActionTimeStamp, ServerId, ClientAuditEntryId, ClientUserId
e.SetChildValue(
systemContext,
BrowseNames.SourceName,
"SecureChannel/CloseSecureChannel",
false);
const string clientUserId = "System/CloseSecureChannel";
//operationContext.UserIdentity?.DisplayName, or ”System/CloseSecureChannel”
e.SetChildValue(systemContext, BrowseNames.ClientUserId, clientUserId, false);
e.SetChildValue(systemContext, BrowseNames.SourceNode, ObjectIds.Server, false);
e.SetChildValue(
systemContext,
BrowseNames.LocalTime,
TimeZoneDataType.Local,
false);
// set AuditSecurityEventType fields
e.SetChildValue(systemContext, BrowseNames.StatusCodeId, statusCode, false);
// set AuditChannelEventType fields
e.SetChildValue(systemContext, BrowseNames.SecureChannelId, globalChannelId, false);
server.ReportAuditEvent(systemContext, e);
}
catch (Exception ex)
{
logger.LogError(ex, "Error while reporting AuditOpenSecureChannelEvent event.");
}
}
///
/// Reports the AuditUpdateMethodEventType
///
/// The server which reports audit events.
/// Server information.
/// The id of the object where the method is executed.
/// The NodeId of the object that the method resides in.
/// The InputArguments of the method
/// Custom message for delete nodes.
/// The resulting status code.
/// A contextual logger to log to
public static void ReportAuditUpdateMethodEvent(
this IAuditEventServer? server,
ISystemContext systemContext,
NodeId objectId,
NodeId methodId,
ArrayOf inputArgs,
string customMessage,
StatusCode statusCode,
ILogger logger)
{
if (server?.Auditing != true)
{
// current server does not support auditing
return;
}
try
{
var e = new AuditUpdateMethodEventState(null);
var message = new TranslationInfo(
"AuditUpdateMethodEventState",
"en-US",
$"'{customMessage}' returns StatusCode: {statusCode.ToString(null, CultureInfo.InvariantCulture)}.");
e.Initialize(
systemContext,
null,
EventSeverity.Min,
new LocalizedText(message),
StatusCode.IsGood(statusCode),
DateTime.UtcNow
); // initializes Status, ActionTimeStamp, ServerId, ClientAuditEntryId, ClientUserId
e.SetChildValue(systemContext, BrowseNames.SourceNode, objectId, false);
e.SetChildValue(systemContext, BrowseNames.SourceName, "Attribute/Call", false);
e.SetChildValue(
systemContext,
BrowseNames.LocalTime,
TimeZoneDataType.Local,
false);
e.SetChildValue(
systemContext,
BrowseNames.ClientUserId,
(systemContext as ISessionSystemContext)?.UserIdentity?.DisplayName!,
false);
e.SetChildValue(
systemContext,
BrowseNames.ClientAuditEntryId,
systemContext.AuditEntryId!,
false);
e.SetChildValue(systemContext, BrowseNames.MethodId, methodId, false);
e.SetChildValue(systemContext, BrowseNames.InputArguments, inputArgs, false);
server.ReportAuditEvent(systemContext, e);
}
catch (Exception ex)
{
logger.LogError(ex, "Error while reporting AuditDeleteNodesEvent event.");
}
}
///
/// Reports an TrustListUpdatedAudit event.
///
/// The trustlist node.
/// The current system context
/// The object id where the truest list update methods was called
/// The source name string
/// The id of the method that was called
/// The input parameters of the called method
/// The status code resulted when the TrustList was updated
/// A contextual logger to log to
public static void ReportTrustListUpdatedAuditEvent(
this TrustListState node,
ISystemContext systemContext,
NodeId objectId,
string sourceName,
NodeId methodId,
ArrayOf inputParameters,
StatusCode statusCode,
ILogger logger)
{
try
{
var e = new TrustListUpdatedAuditEventState(null);
var message = new TranslationInfo(
"TrustListUpdatedAuditEvent",
"en-US",
$"TrustListUpdatedAuditEvent result is: {statusCode.ToString(null, CultureInfo.InvariantCulture)}");
e.Initialize(
systemContext,
null,
EventSeverity.Min,
new LocalizedText(message),
StatusCode.IsGood(statusCode),
DateTime.UtcNow
); // initializes Status, ActionTimeStamp, ServerId, ClientAuditEntryId, ClientUserId
e.SetChildValue(systemContext, BrowseNames.SourceNode, objectId, false);
e.SetChildValue(systemContext, BrowseNames.SourceName, sourceName, false);
e.SetChildValue(
systemContext,
BrowseNames.LocalTime,
TimeZoneDataType.Local,
false);
e.SetChildValue(systemContext, BrowseNames.MethodId, methodId, false);
e.SetChildValue(systemContext, BrowseNames.InputArguments, inputParameters, false);
node?.ReportEvent(systemContext, e);
}
catch (Exception ex)
{
logger.LogError(ex, "Error while reporting ReportTrustListUpdatedAuditEvent event.");
}
}
///
/// Reports an TrustListUpdatedAudit event.
///
/// The trustlist node.
/// The current system context
/// The object id where the truest list update methods was called
/// The source name string
/// The id of the method that was called
/// The input parameters of the called method
/// A contextual logger to log to
public static void ReportTrustListUpdateRequestedAuditEvent(
this TrustListState node,
ISystemContext systemContext,
NodeId objectId,
string sourceName,
NodeId methodId,
ArrayOf inputParameters,
ILogger logger)
{
try
{
var e = new TrustListUpdateRequestedAuditEventState(null);
var message = new TranslationInfo(
"TrustListUpdateRequestedAuditEvent",
"en-US",
"TrustListUpdateRequestedAuditEvent.");
e.Initialize(systemContext, null, EventSeverity.Min, new LocalizedText(message), true, DateTime.UtcNow); // initializes Status, ActionTimeStamp, ServerId, ClientAuditEntryId, ClientUserId
e.SetChildValue(systemContext, BrowseNames.SourceNode, objectId, false);
e.SetChildValue(systemContext, BrowseNames.SourceName, sourceName, false);
e.SetChildValue(
systemContext,
BrowseNames.LocalTime,
TimeZoneDataType.Local,
false);
e.SetChildValue(systemContext, BrowseNames.MethodId, methodId, false);
e.SetChildValue(systemContext, BrowseNames.InputArguments, inputParameters, false);
node?.ReportEvent(systemContext, e);
}
catch (Exception ex)
{
logger.LogError(
ex,
"Error while reporting TrustListUpdateRequestedAuditEvent event.");
}
}
///
/// Initialize the properties of an AuditUpdateEventState.
///
/// AuditUpdate event reference
/// The current system context.
/// Audit event name
/// Source name
/// History update details
/// The resulting status code
private static void InitializeAuditHistoryUpdateEvent(
AuditUpdateEventState e,
ISystemContext systemContext,
string auditEventName,
string sourceName,
HistoryUpdateDetails historyUpdateDetails,
StatusCode statusCode)
{
var message = new TranslationInfo(
auditEventName,
"en-US",
$"{auditEventName} has Result: {statusCode.ToString(null, CultureInfo.InvariantCulture)}.");
e.Initialize(
systemContext,
null,
EventSeverity.Min,
new LocalizedText(message),
StatusCode.IsGood(statusCode),
DateTime.UtcNow
); // initializes Status, ActionTimeStamp, ServerId, ClientAuditEntryId, ClientUserId
e.SetChildValue(
systemContext,
BrowseNames.SourceNode,
historyUpdateDetails.NodeId,
false);
e.SetChildValue(systemContext, BrowseNames.SourceName, sourceName, false);
e.SetChildValue(systemContext, BrowseNames.LocalTime, TimeZoneDataType.Local, false);
e.SetChildValue(
systemContext,
BrowseNames.ClientUserId,
(systemContext as ISessionSystemContext)?.UserIdentity?.DisplayName!,
false);
e.SetChildValue(
systemContext,
BrowseNames.ClientAuditEntryId,
systemContext.AuditEntryId!,
false);
e.SetChildValue(
systemContext,
BrowseNames.ParameterDataTypeId,
historyUpdateDetails.TypeId,
false);
}
///
/// Initializes a session audit event.
///
private static void InitializeAuditSessionEvent(
ISystemContext systemContext,
AuditEventState e,
TranslationInfo message,
bool status,
ISession session,
string auditEntryId)
{
e.Initialize(
systemContext,
null,
EventSeverity.Min,
new LocalizedText(message),
status,
DateTime.UtcNow);
e.SetChildValue(systemContext, BrowseNames.SourceNode, ObjectIds.Server, false);
e.SetChildValue(systemContext, BrowseNames.ClientAuditEntryId, auditEntryId, false);
if (session != null)
{
// set AuditEventType properties
e.SetChildValue(
systemContext,
BrowseNames.ClientUserId,
session.Identity?.DisplayName!,
false);
// set AuditCreateSessionEventType & AuditActivateSessionsEventType properties
e.SetChildValue(
systemContext,
BrowseNames.SecureChannelId,
session.SecureChannelId,
false);
// set AuditSessionEventType
e.SetChildValue(systemContext, BrowseNames.SessionId, session.Id, false);
}
}
}
}