├── SerilogExamplesAPI ├── SerilogExamplesAPI │ ├── SerilogExamplesAPI.http │ ├── SerilogOperators │ │ ├── CustomizedEmailAddressMaskingOperator.cs │ │ └── PhoneNumberMaskingOperator.cs │ ├── appsettings.json │ ├── Properties │ │ └── launchSettings.json │ ├── Program.cs │ ├── SerilogExamplesAPI.csproj │ └── Controllers │ │ └── SerilogController.cs └── SerilogExamplesAPI.sln ├── .gitignore ├── catalog-info.yaml └── README.md /SerilogExamplesAPI/SerilogExamplesAPI/SerilogExamplesAPI.http: -------------------------------------------------------------------------------- 1 | @SerilogExamplesAPI_HostAddress = http://localhost:5226 2 | 3 | GET {{SerilogExamplesAPI_HostAddress}}/serilog/ 4 | Accept: application/json 5 | 6 | ### 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | # This .gitignore file was automatically created by Microsoft(R) Visual Studio. 3 | ################################################################################ 4 | 5 | *.user 6 | *.suo 7 | /.vs/SerilogExamples/v17 8 | /SerilogExamplesAPI/SerilogExamplesAPI/obj 9 | /SerilogExamplesAPI/SerilogExamplesAPI/bin 10 | /SerilogExamplesAPI/.vs/SerilogExamplesAPI/FileContentIndex 11 | -------------------------------------------------------------------------------- /SerilogExamplesAPI/SerilogExamplesAPI/SerilogOperators/CustomizedEmailAddressMaskingOperator.cs: -------------------------------------------------------------------------------- 1 | using System.Text.RegularExpressions; 2 | using Serilog.Enrichers.Sensitive; 3 | 4 | namespace SerilogExamplesAPI.SerilogOperators; 5 | 6 | public class CustomizedEmailAddressMaskingOperator : EmailAddressMaskingOperator 7 | { 8 | protected override string PreprocessMask(string mask, Match match) 9 | { 10 | var parts = match.Value.Split('@'); 11 | 12 | return mask + "@" + parts[1]; 13 | } 14 | } -------------------------------------------------------------------------------- /catalog-info.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: backstage.io/v1alpha1 2 | kind: Component 3 | metadata: 4 | name: SerilogExamples 5 | description: A C# Serilog Library 6 | annotations: 7 | backstage.io/techdocs-ref: dir:. 8 | github.com/project-slug: kalebasiyakup/SerilogExamples 9 | tags: 10 | - c# 11 | links: 12 | - url: https://github.com/kalebasiyakup 13 | title: Github Dashboard 14 | icon: dashboard 15 | type: admin-dashboard 16 | spec: 17 | type: service 18 | lifecycle: production 19 | owner: yakupkalebasi 20 | system: github-project 21 | 22 | --- 23 | apiVersion: backstage.io/v1alpha1 24 | kind: System 25 | metadata: 26 | name: github-project 27 | description: github-project info 28 | spec: 29 | owner: yakupkalebasi 30 | domain: infa 31 | -------------------------------------------------------------------------------- /SerilogExamplesAPI/SerilogExamplesAPI.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SerilogExamplesAPI", "SerilogExamplesAPI\SerilogExamplesAPI.csproj", "{B3F44D8F-EBA1-4EDA-B90E-2B0190EAFEE3}" 4 | EndProject 5 | Global 6 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 7 | Debug|Any CPU = Debug|Any CPU 8 | Release|Any CPU = Release|Any CPU 9 | EndGlobalSection 10 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 11 | {B3F44D8F-EBA1-4EDA-B90E-2B0190EAFEE3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 12 | {B3F44D8F-EBA1-4EDA-B90E-2B0190EAFEE3}.Debug|Any CPU.Build.0 = Debug|Any CPU 13 | {B3F44D8F-EBA1-4EDA-B90E-2B0190EAFEE3}.Release|Any CPU.ActiveCfg = Release|Any CPU 14 | {B3F44D8F-EBA1-4EDA-B90E-2B0190EAFEE3}.Release|Any CPU.Build.0 = Release|Any CPU 15 | EndGlobalSection 16 | EndGlobal 17 | -------------------------------------------------------------------------------- /SerilogExamplesAPI/SerilogExamplesAPI/SerilogOperators/PhoneNumberMaskingOperator.cs: -------------------------------------------------------------------------------- 1 | using System.Text.RegularExpressions; 2 | using Serilog.Enrichers.Sensitive; 3 | 4 | namespace SerilogExamplesAPI.SerilogOperators; 5 | 6 | public class PhoneNumberMaskingOperator : RegexMaskingOperator 7 | { 8 | private const string PhonePattern = 9 | @"(?:\+?\d{1,3})?[-.\s]?(\(?\d{3}\)?)?[-.\s]?(\d{3})[-.\s]?(\d{4})"; 10 | 11 | public PhoneNumberMaskingOperator() : base(PhonePattern, RegexOptions.IgnoreCase | RegexOptions.Compiled) 12 | { 13 | } 14 | 15 | protected override string PreprocessInput(string input) 16 | { 17 | return input; 18 | } 19 | 20 | protected override string PreprocessMask(string mask, Match match) 21 | { 22 | string lastThreeDigits = match.Value.Length >= 3 ? match.Value[^3..] : match.Value; 23 | string maskedPart = new string('*', match.Value.Length - 3); 24 | 25 | return maskedPart + lastThreeDigits; 26 | } 27 | 28 | protected override bool ShouldMaskInput(string input) 29 | { 30 | return Regex.IsMatch(input, PhonePattern); 31 | } 32 | } -------------------------------------------------------------------------------- /SerilogExamplesAPI/SerilogExamplesAPI/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.AspNetCore": "Warning" 6 | } 7 | }, 8 | "Serilog": { 9 | "Using": [ "Serilog.Sinks.Console", "Serilog.Sinks.File" ], 10 | "MinimumLevel": { 11 | "Default": "Information", 12 | "Override": { 13 | "Microsoft": "Warning", 14 | "System": "Warning" 15 | } 16 | }, 17 | "WriteTo": [ 18 | { 19 | "Name": "Console" 20 | }, 21 | { 22 | "Name": "File", 23 | "Args": { 24 | "path": "Logs\\log-development..json", 25 | "rollingInterval": "Day", 26 | "rollOnFileSizeLimit": true, 27 | "formatter": "Serilog.Formatting.Compact.CompactJsonFormatter, Serilog.Formatting.Compact" 28 | } 29 | } 30 | ], 31 | "Enrich": [ 32 | "FromLogContext", 33 | "WithMachineName", 34 | "WithProcessId", 35 | "WithThreadId", 36 | "WithClientIp" 37 | ], 38 | "Properties": { 39 | "Application": "Your ASP.NET Core App", 40 | "Environment": "Development" 41 | } 42 | }, 43 | "AllowedHosts": "*" 44 | } 45 | -------------------------------------------------------------------------------- /SerilogExamplesAPI/SerilogExamplesAPI/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json.schemastore.org/launchsettings.json", 3 | "iisSettings": { 4 | "windowsAuthentication": false, 5 | "anonymousAuthentication": true, 6 | "iisExpress": { 7 | "applicationUrl": "http://localhost:14426", 8 | "sslPort": 44340 9 | } 10 | }, 11 | "profiles": { 12 | "http": { 13 | "commandName": "Project", 14 | "dotnetRunMessages": true, 15 | "launchBrowser": true, 16 | "launchUrl": "swagger", 17 | "applicationUrl": "http://localhost:5226", 18 | "environmentVariables": { 19 | "ASPNETCORE_ENVIRONMENT": "Development" 20 | } 21 | }, 22 | "https": { 23 | "commandName": "Project", 24 | "dotnetRunMessages": true, 25 | "launchBrowser": true, 26 | "launchUrl": "swagger", 27 | "applicationUrl": "https://localhost:7233;http://localhost:5226", 28 | "environmentVariables": { 29 | "ASPNETCORE_ENVIRONMENT": "Development" 30 | } 31 | }, 32 | "IIS Express": { 33 | "commandName": "IISExpress", 34 | "launchBrowser": true, 35 | "launchUrl": "swagger", 36 | "environmentVariables": { 37 | "ASPNETCORE_ENVIRONMENT": "Development" 38 | } 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /SerilogExamplesAPI/SerilogExamplesAPI/Program.cs: -------------------------------------------------------------------------------- 1 | using Serilog; 2 | using Serilog.Enrichers.Sensitive; 3 | using SerilogExamplesAPI.SerilogOperators; 4 | 5 | var builder = WebApplication.CreateBuilder(args); 6 | 7 | builder.Services.AddControllers(); 8 | builder.Services.AddEndpointsApiExplorer(); 9 | builder.Services.AddSwaggerGen(); 10 | 11 | builder.Host.UseSerilog((context, configuration) => 12 | configuration 13 | .ReadFrom.Configuration(context.Configuration) 14 | .Enrich.WithSensitiveDataMasking(options => 15 | { 16 | options.MaskValue = "****"; 17 | options.MaskProperties = new List { "CUSTOM_PROPERTY" }; 18 | options.Mode = MaskingMode.Globally; 19 | options.MaskingOperators = new List 20 | { 21 | new CustomizedEmailAddressMaskingOperator(), 22 | new IbanMaskingOperator(), 23 | new PhoneNumberMaskingOperator() 24 | }; 25 | }) 26 | ); 27 | 28 | var app = builder.Build(); 29 | 30 | app.UseSerilogRequestLogging(); 31 | 32 | if (app.Environment.IsDevelopment()) 33 | { 34 | app.UseSwagger(); 35 | app.UseSwaggerUI(); 36 | } 37 | 38 | app.UseHttpsRedirection(); 39 | 40 | app.UseAuthorization(); 41 | 42 | app.MapControllers(); 43 | 44 | app.Run(); -------------------------------------------------------------------------------- /SerilogExamplesAPI/SerilogExamplesAPI/SerilogExamplesAPI.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net8.0 5 | enable 6 | enable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /SerilogExamplesAPI/SerilogExamplesAPI/Controllers/SerilogController.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Mvc; 2 | 3 | namespace SerilogExamplesAPI.Controllers; 4 | 5 | [ApiController] 6 | [Route("[controller]")] 7 | public class SerilogController(ILogger logger) : ControllerBase 8 | { 9 | private static readonly string[] Summaries = new[] 10 | { 11 | "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" 12 | }; 13 | 14 | [HttpGet(Name = "GetLog")] 15 | public async Task>> Get() 16 | { 17 | // An e-mail address in text 18 | logger.LogInformation("This is a secret email address: test@test.co.uk"); 19 | 20 | // Works for properties too 21 | logger.LogInformation("This is a secret email address: {Email}", "test@test.co.uk"); 22 | 23 | // IBANs are also masked 24 | logger.LogInformation("Bank transfer from Felix Leiter on TR330006100519700007840000"); 25 | 26 | // IBANs are also masked 27 | logger.LogInformation("Bank transfer from Felix Leiter on {BankAccount}", "TR330006100519700007840000"); 28 | 29 | // Credit card numbers too 30 | logger.LogInformation("Credit Card Number: 4111111111111111"); 31 | 32 | // even works in an embedded XML string 33 | var x = new 34 | { 35 | Key = 12345, 36 | XmlValue = "4111111111111111" 37 | }; 38 | logger.LogInformation("Object dump with embedded credit card: {x}", x); 39 | 40 | //GSM Number 41 | logger.LogInformation("GSM Number: 565009098"); 42 | 43 | //Custom 44 | logger.LogInformation("This is a CUSTOM_PROPERTY sensitive {CUSTOM_PROPERTY}", "Deneme"); 45 | 46 | if (!Directory.Exists("Logs")) 47 | { 48 | return NotFound("Logs directory not found."); 49 | } 50 | 51 | try 52 | { 53 | var logFiles = Directory.GetFiles("Logs", "*.json"); 54 | 55 | var logsContent = await Task.WhenAll(logFiles.Select(async logFile => 56 | { 57 | await using var stream = new FileStream(logFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); 58 | using var reader = new StreamReader(stream); 59 | var content = await reader.ReadToEndAsync(); 60 | return new 61 | { 62 | FileName = Path.GetFileName(logFile), 63 | Content = content 64 | }; 65 | })); 66 | 67 | return Ok(logsContent); 68 | } 69 | catch (System.Exception ex) 70 | { 71 | return StatusCode(500, $"Internal server error: {ex.Message}"); 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Serilog Examples - Serilog ve Serilog.Enrichers.Sensitive Kullanımı 2 | 3 | Bu proje, **Serilog** ve **Serilog.Enrichers.Sensitive** ile loglama işlemlerinde hassas verilerin maskeleme örneğini içermektedir. Uygulama içinde bazı hassas verilerin (e-posta, telefon numarası, kredi kartı bilgileri vb.) loglanırken gizlenmesi sağlanır. 4 | 5 | ## Proje Kurulumu 6 | 7 | Projeyi klonladıktan sonra, bağımlılıkları yüklemek için aşağıdaki komutu çalıştırın: 8 | 9 | ```bash 10 | dotnet restore 11 | ``` 12 | 13 | Ardından projeyi başlatabilirsiniz: 14 | 15 | ```bash 16 | dotnet run 17 | ``` 18 | 19 | ## Kullanılan Kütüphaneler 20 | 21 | - **Serilog**: .NET uygulamalarında esnek ve yapılandırılabilir loglama çözümü sunar. 22 | - **Serilog.Enrichers.Sensitive**: Serilog ile hassas verilerin maskelenmesini sağlar. 23 | 24 | ## Yapılandırma 25 | 26 | Hassas verilerin maskeleme ayarları `appsettings.json` dosyasında tanımlanmıştır. Dosyaya örnek olarak aşağıdaki yapılandırma eklenmiştir: 27 | 28 | ```json 29 | { 30 | "Logging": { 31 | "LogLevel": { 32 | "Default": "Information", 33 | "Microsoft.AspNetCore": "Warning" 34 | } 35 | }, 36 | "Serilog": { 37 | "Using": [ "Serilog.Sinks.Console", "Serilog.Sinks.File" ], 38 | "MinimumLevel": { 39 | "Default": "Information", 40 | "Override": { 41 | "Microsoft": "Warning", 42 | "System": "Warning" 43 | } 44 | }, 45 | "WriteTo": [ 46 | { 47 | "Name": "Console" 48 | }, 49 | { 50 | "Name": "File", 51 | "Args": { 52 | "path": "Logs\\log-development..json", 53 | "rollingInterval": "Day", 54 | "rollOnFileSizeLimit": true, 55 | "formatter": "Serilog.Formatting.Compact.CompactJsonFormatter, Serilog.Formatting.Compact" 56 | } 57 | } 58 | ], 59 | "Enrich": [ 60 | "FromLogContext", 61 | "WithMachineName", 62 | "WithProcessId", 63 | "WithThreadId", 64 | "WithClientIp" 65 | ], 66 | "Properties": { 67 | "Application": "Your ASP.NET Core App", 68 | "Environment": "Development" 69 | } 70 | }, 71 | "AllowedHosts": "*" 72 | } 73 | ``` 74 | 75 | ## Maskelenmiş Veriler 76 | 77 | `Serilog.Enrichers.Sensitive`, belirli türdeki hassas bilgilerin (örneğin e-posta adresleri, telefon numaraları) otomatik olarak maskelenmesini sağlar. Bu örnekte: 78 | 79 | - **E-posta adresleri** (Orjinalin dışında Custom olarak düzeneleme yapılmıştır.) 80 | - **IBAN numaraları** 81 | - **Telefon numaraları** Normal de böyle bir tanımı yok. Ama RegexMaskingOperator kalıtım alarak istediğiniz Operator yazabilirsiniz diye örnek yapmak istedim. 82 | 83 | gibi bilgiler otomatik olarak maskelenmiştir. 84 | 85 | ### Örnek Kod 86 | 87 | ```csharp 88 | logger.LogInformation("This is a secret email address: test@test.co.uk"); 89 | 90 | logger.LogInformation("This is a secret email address: {Email}", "test@test.co.uk"); 91 | 92 | logger.LogInformation("Bank transfer from Felix Leiter on TR330006100519700007840000"); 93 | 94 | logger.LogInformation("Bank transfer from Felix Leiter on {BankAccount}", "TR330006100519700007840000"); 95 | 96 | logger.LogInformation("Credit Card Number: 4111111111111111"); 97 | 98 | var x = new 99 | { 100 | Key = 12345, 101 | XmlValue = "4111111111111111" 102 | }; 103 | logger.LogInformation("Object dump with embedded credit card: {x}", x); 104 | 105 | logger.LogInformation("GSM Number: 565009098"); 106 | 107 | logger.LogInformation("This is a CUSTOM_PROPERTY sensitive {CUSTOM_PROPERTY}", "Deneme"); 108 | ``` 109 | 110 | Loglama çıktısında hassas bilgiler aşağıdaki gibi maskelenmiş olarak görülecektir: 111 | 112 | ```json 113 | { 114 | "Email": "****@test.co.uk", 115 | "Iban": "****", 116 | "Card Number": "********111111111", 117 | "GSM Number": "*****09098" 118 | } 119 | ``` 120 | 121 | ## Lisans 122 | 123 | Bu proje [MIT Lisansı](LICENSE) ile lisanslanmıştır. 124 | --------------------------------------------------------------------------------