Introduction
Logging is an essential aspect of application development, offering insights into application behavior and performance. However, logging sensitive data like passwords or personal information can pose security risks. In this blog post, we'll delve into implementing structured logging with Serilog and sanitizing sensitive data before logging it, utilizing the Console sink as an example.
Overview of Structured Logging
Structured logging entails logging data in a structured format, typically as key-value pairs. This format enhances searchability, filtering, and analysis of log data compared to traditional plain text logging.
The source code can be downloaded from GitHub
Introduction to Serilog
Serilog is a popular logging library for .NET, supporting structured logging out of the box. It offers a versatile configuration API and various sinks for directing log data to different destinations.
Setting up Serilog with Console Sink
The Console sink is a straightforward sink provided by Serilog for logging to the console. It is commonly used during development or debugging. Setting up Serilog with the Console sink requires minimal configuration.
Install packages Serilog and Serilog.Sinks.Console
using Serilog;
Log.Logger = new LoggerConfiguration()
.WriteTo.Console()
.CreateLogger();
Log.Information("Hello, structured logging!");
Log.CloseAndFlush();
Sanitizing Sensitive Data
Sensitive data, such as passwords or personal information, should not be logged in plain text to prevent exposure. We can use Serilog's Destructure.UsingAttributes() method to sanitize sensitive data before logging it.
Configure the sanitization
Install the package: Destructurama. Attributed
using Destructurama;
using Serilog;
Log.Logger = new LoggerConfiguration()
.WriteTo.Console()
.Destructure.UsingAttributes() //.Destructure.ByTransforming<object>(LogSanitizer.SanitizeSensitiveData)
.CreateLogger();
Structured Logging Example
Let's demonstrate implementing structured logging with Serilog and sensitive data sanitization.
using Destructurama.Attributed;
namespace SanitizeLogData
{
public class SensitiveData
{
[NotLogged]
public string Password { get; set; }
public string Username { get; set; }
public Address Address { get; set; }
}
public class Address
{
public string Street { get; set; }
public string ZipCode { get; set; }
}
}
Add the attribute [NotLogged] on the properties that need to be excluded while logging.
using Destructurama;
using SanitizeLogData;
using Serilog;
Log.Logger = new LoggerConfiguration()
.WriteTo.Console()
.Destructure.UsingAttributes()
//.Destructure.ByTransforming<object>(LogSanitizer.SanitizeSensitiveData)
.CreateLogger();
var sensitiveData = new SensitiveData
{
Username = "praveendran",
Password = "supersecret",
Address = new Address
{
Street = "123 Main St",
ZipCode = "12345"
}
};
Log.Information("Sensitive data: {@SensitiveData}", sensitiveData);
Log.CloseAndFlush();
Execute the console, you can see the below output where password property has been excluded from the log.
This approach ensures that the sensitive data is properly sanitized(excluded) before being logged, regardless of the Serilog configuration