/// <summary> /// Writes the specified audit log entry. /// </summary> /// <param name="entryData">The entry data.</param> /// <exception cref="System.ArgumentNullException">entryData</exception> public void Write(IAuditLogEntryData entryData) { if (entryData == null) { throw new ArgumentNullException(nameof(entryData)); } using (new SecurityBypassContext()) { var syslogMessage = new SyslogMessage { Facility = SyslogFacility.LogAudit, Severity = ConvertToSyslogSeverity(entryData.SeverityEnum), Timestamp = new DateTimeOffset(entryData.CreatedDate), HostName = _hostName, AppName = _applicationName, ProcId = _processName, MsgId = entryData.AuditLogEntryMetadata.MessageId }; syslogMessage.StructuredDataElements.Add(CreateBaseMsgData(entryData)); syslogMessage.StructuredDataElements.Add(CreateSpecificMsgData(entryData)); syslogMessage.StructuredDataElements.Add(CreateSystemInfoData()); syslogMessage.StructuredDataElements.Add(CreateOriginData(_ipHostEntry)); _syslogMessageWriter.Write(syslogMessage); } }
/// <summary> /// Validates the message. /// </summary> /// <param name="message">The message.</param> /// <param name="auditLogEventData">The audit log event data.</param> /// <returns></returns> private bool ValidateMessage(SyslogMessage message, IAuditLogEntryData auditLogEventData) { SyslogApplicationSettings syslogApplicationSettings = ConfigurationSettings.GetSyslogConfigurationSection().SyslogApplicationSettings; SyslogSeverity severity; string databaseName = string.Empty; string databaseServer = string.Empty; var databaseConfiguration = ConfigurationSettings.GetDatabaseConfigurationSection(); if (databaseConfiguration?.ConnectionSettings != null) { databaseName = databaseConfiguration.ConnectionSettings.Database; databaseServer = databaseConfiguration.ConnectionSettings.Server; } switch (auditLogEventData.SeverityEnum) { case AuditLogSeverityEnum_Enumeration.AuditLogInformation: severity = SyslogSeverity.Informational; break; case AuditLogSeverityEnum_Enumeration.AuditLogWarning: severity = SyslogSeverity.Warning; break; case AuditLogSeverityEnum_Enumeration.AuditLogError: severity = SyslogSeverity.Error; break; default: throw new ArgumentException("auditLogEventData"); } Assert.AreEqual(1, message.Version, "The version is incorrect."); Assert.AreEqual(SyslogFacility.LogAudit, message.Facility, "The facility is incorrect"); Assert.AreEqual(severity, message.Severity, "The severity is incorrect"); Assert.AreEqual(syslogApplicationSettings.ApplicationName, message.AppName, "The app name is incorrect"); Assert.AreEqual(auditLogEventData.AuditLogEntryMetadata.MessageId, message.MsgId, "The message id is invalid"); Assert.AreEqual(4, message.StructuredDataElements.Count, "The number of structured data elements is invalid"); Assert.AreEqual("audit@" + syslogApplicationSettings.EnterpriseId, message.StructuredDataElements[0].SdId); Assert.AreEqual(auditLogEventData.AuditLogEntryMetadata.MessageId + "@" + syslogApplicationSettings.EnterpriseId, message.StructuredDataElements[1].SdId); Assert.AreEqual("systemInfo@" + syslogApplicationSettings.EnterpriseId, message.StructuredDataElements[2].SdId); Assert.AreEqual("installDirectory", message.StructuredDataElements[2].Parameters[0].Name); Assert.AreEqual(SystemInfo.InstallFolder.Replace("\\", "/"), message.StructuredDataElements[2].Parameters[0].Value); Assert.AreEqual("databaseName", message.StructuredDataElements[2].Parameters[1].Name); Assert.AreEqual(databaseName, message.StructuredDataElements[2].Parameters[1].Value); Assert.AreEqual("databaseServer", message.StructuredDataElements[2].Parameters[2].Name); Assert.AreEqual(databaseServer, message.StructuredDataElements[2].Parameters[2].Value); Assert.AreEqual(SyslogOriginConstants.Origin, message.StructuredDataElements[3].SdId); return(true); }
/// <summary> /// Creates the syslog structured data containing parameters common to all audit log messages. /// </summary> /// <param name="entryData">The entry data.</param> /// <returns></returns> private SyslogSdElement CreateBaseMsgData(IAuditLogEntryData entryData) { var sdElement = new SyslogSdElement($"audit@{_enterpriseId.ToString(CultureInfo.InvariantCulture)}"); sdElement.Parameters.Add(new SyslogSdParameter("msgId", entryData.AuditLogEntryMetadata.MessageId)); sdElement.Parameters.Add(new SyslogSdParameter("success", entryData.Success.ToString())); sdElement.Parameters.Add(new SyslogSdParameter("tenant", RequestContext.GetContext().Tenant.Name)); sdElement.Parameters.Add(new SyslogSdParameter("user", entryData.UserName)); return(sdElement); }
/// <summary> /// Verifies the audit log data. /// </summary> /// <param name="data">The data.</param> /// <param name="expectedSuccess">if set to <c>true</c> [expected success].</param> /// <param name="expectedTypeAlias">The expected type alias.</param> /// <param name="expectedMetadataTypeAlias">The expected metadata type alias.</param> /// <param name="expectedParametersCount">The expected parameters count.</param> /// <returns></returns> private bool VerifyAuditLogData(IAuditLogEntryData data, bool expectedSuccess, string expectedTypeAlias, string expectedMetadataTypeAlias, int expectedParametersCount) { // Get the severity based on success or failure AuditLogSeverityEnum severity = expectedSuccess ? data.AuditLogEntryMetadata.SeveritySuccess : data.AuditLogEntryMetadata.SeverityFailure; AuditLogSeverityEnum_Enumeration expectedSeverityEnum = AuditLogSeverityEnum.ConvertAliasToEnum(severity.Alias) ?? AuditLogSeverityEnum_Enumeration.AuditLogInformation; return(data.Success == expectedSuccess && data.AuditLogEntryType.Alias == expectedTypeAlias && data.AuditLogEntryMetadata.Alias == expectedMetadataTypeAlias && data.SeverityEnum == expectedSeverityEnum && data.Parameters.Count == expectedParametersCount && data.Parameters.Values.All(v => v != null)); }
/// <summary> /// Determines whether this instance can write the specified entry data. /// </summary> /// <param name="entryData">The entry data.</param> /// <returns></returns> /// <exception cref="System.ArgumentNullException">entryData</exception> private bool CanWrite(IAuditLogEntryData entryData) { if (entryData == null) { throw new ArgumentNullException(nameof(entryData)); } // When running as the global tenant do not write to the entity model. // This can occur when creating/deleting tenants if (RequestContext.GetContext().Tenant.Id == 0) { return(false); } return(CanWrite(entryData.Severity)); }
/// <summary> /// Writes the specified audit log entry. /// </summary> /// <param name="entryData">The entry data.</param> /// <exception cref="System.ArgumentNullException">entryData</exception> public void Write(IAuditLogEntryData entryData) { if (entryData == null) { throw new ArgumentNullException(nameof(entryData)); } // Writes an entry to the event log var eventLogMessage = new StringBuilder(); eventLogMessage.AppendLine($"Audit log entry. Type: '{entryData.AuditLogEntryType.Name}'"); eventLogMessage.AppendLine($"AuditLogMessage: '{entryData.Message}'"); eventLogMessage.AppendLine($"Success: '{entryData.Success}'"); eventLogMessage.AppendLine($"Severity: '{entryData.SeverityEnum}'"); eventLogMessage.AppendLine($"UserName: '******'"); eventLogMessage.AppendLine($"CreatedDate: '{entryData.CreatedDate.ToLocalTime().ToString("o")}'"); if (entryData.Parameters.Count > 0) { eventLogMessage.AppendLine("Parameters:"); foreach (var kvp in entryData.Parameters) { eventLogMessage.AppendLine($"{kvp.Key}: '{kvp.Value}'"); } } switch (entryData.SeverityEnum) { case AuditLogSeverityEnum_Enumeration.AuditLogError: _eventLog.WriteError(eventLogMessage.ToString()); break; case AuditLogSeverityEnum_Enumeration.AuditLogInformation: _eventLog.WriteInformation(eventLogMessage.ToString()); break; case AuditLogSeverityEnum_Enumeration.AuditLogWarning: _eventLog.WriteWarning(eventLogMessage.ToString()); break; } }
/// <summary> /// Creates the syslog structured data containing parameters specific to the audit log message. /// </summary> /// <param name="entryData">The entry data.</param> /// <returns></returns> private SyslogSdElement CreateSpecificMsgData(IAuditLogEntryData entryData) { var sdElement = new SyslogSdElement($"{entryData.AuditLogEntryMetadata.MessageId}@{_enterpriseId.ToString(CultureInfo.InvariantCulture)}"); // Set type specific fields foreach (var kvp in entryData.Parameters) { if (kvp.Value == null) { continue; } string value = kvp.Value.ToString(); if (kvp.Value is DateTime?) { value = $"{kvp.Value:o}"; } sdElement.Parameters.Add(new SyslogSdParameter(kvp.Key, value)); } return(sdElement); }
/// <summary> /// Writes the specified audit log entry. /// </summary> /// <param name="entryData">The entry data.</param> /// <exception cref="System.ArgumentNullException">entryData</exception> public void Write(IAuditLogEntryData entryData) { if (entryData == null) { throw new ArgumentNullException(nameof(entryData)); } using (DatabaseContextInfo.SetContextInfo("Write Audit Log")) using (new SecurityBypassContext()) { if (!CanWrite(entryData)) { return; } IEntity logEntry = Entity.Create(entryData.AuditLogEntryType); // Set type specific fields foreach (var kvp in entryData.Parameters) { logEntry.SetField(kvp.Key, kvp.Value); } // Set base type fields and relationships logEntry.SetField("name", entryData.AuditLogEntryType.Name); logEntry.SetField("auditLogEntrySuccess", entryData.Success); logEntry.SetField("auditLogEntryUser", entryData.UserName); logEntry.SetField("auditLogEntryCreatedDate", entryData.CreatedDate); logEntry.SetRelationships("auditLogEntrySeverity", new EntityRelationship <AuditLogSeverityEnum>(entryData.Severity).ToEntityRelationshipCollection(), Direction.Forward); logEntry.SetField("auditLogEntryMessage", entryData.Message); logEntry.Save(); _auditLogDeleter.Purge(); } }