From 3452dfb19f4c154414c171b633e293bdfdd6ed55 Mon Sep 17 00:00:00 2001 From: Matt Gibson Date: Mon, 26 Sep 2022 18:49:28 -0400 Subject: [PATCH] Add logging to tokenables (#2303) * Add logging to tokenables (#2298) * Add logging to token usages * Add settings manipulation of log levels * Maintain no logging for dev * Log exception causing Token failure in TryUnprotect * dotnet format :robot: * Added deconstruction operator on new debug logs. * Split off log level settings into separate files * Improve log messages * dotnet format :robot: * Fix token serialization * Final review notes Co-authored-by: Todd Martin <> (cherry picked from commit c8c9b32904f398fe02448795df6298dfd02c25ef) * Added missing } * Linting fix. * Add logger to constructor Co-authored-by: Todd Martin <> --- bitwarden_license/src/Scim/Program.cs | 5 +- bitwarden_license/src/Sso/Program.cs | 5 +- src/Admin/Program.cs | 5 +- src/Api/Program.cs | 12 ++- src/Billing/Program.cs | 10 +-- ...OrganizationServiceCollectionExtensions.cs | 4 +- src/Core/Settings/GlobalSettings.cs | 5 +- src/Core/Settings/IGlobalSettings.cs | 1 + src/Core/Settings/ILogLevelSettings.cs | 75 +++++++++++++++++++ .../LoggingSettings/AdminLogLevelSettings.cs | 10 +++ .../LoggingSettings/ApiLogLevelSettings.cs | 12 +++ .../BillingLogLevelSettings.cs | 10 +++ .../LoggingSettings/EventsLogLevelSettings.cs | 10 +++ .../EventsProcessorLogLevelSettings.cs | 9 +++ .../LoggingSettings/IconsLogLevelSettings.cs | 9 +++ .../IdentityLogLevelSettings.cs | 11 +++ .../LoggingSettings/LogLevelSettings.cs | 17 +++++ .../NotificationsLogLevelSettings.cs | 10 +++ .../LoggingSettings/ScimLogLevelSettings.cs | 9 +++ .../LoggingSettings/SsoLogLevelSettings.cs | 9 +++ src/Core/Tokens/DataProtectorTokenFactory.cs | 12 ++- src/Core/Tokens/Token.cs | 25 ++++++- src/Core/Utilities/LoggerFactoryExtensions.cs | 11 +-- src/Events/Program.cs | 7 +- src/EventsProcessor/Program.cs | 3 +- src/Icons/Program.cs | 3 +- src/Identity/Program.cs | 12 ++- src/Notifications/Program.cs | 6 +- .../Utilities/ServiceCollectionExtensions.cs | 10 ++- 29 files changed, 269 insertions(+), 58 deletions(-) create mode 100644 src/Core/Settings/ILogLevelSettings.cs create mode 100644 src/Core/Settings/LoggingSettings/AdminLogLevelSettings.cs create mode 100644 src/Core/Settings/LoggingSettings/ApiLogLevelSettings.cs create mode 100644 src/Core/Settings/LoggingSettings/BillingLogLevelSettings.cs create mode 100644 src/Core/Settings/LoggingSettings/EventsLogLevelSettings.cs create mode 100644 src/Core/Settings/LoggingSettings/EventsProcessorLogLevelSettings.cs create mode 100644 src/Core/Settings/LoggingSettings/IconsLogLevelSettings.cs create mode 100644 src/Core/Settings/LoggingSettings/IdentityLogLevelSettings.cs create mode 100644 src/Core/Settings/LoggingSettings/LogLevelSettings.cs create mode 100644 src/Core/Settings/LoggingSettings/NotificationsLogLevelSettings.cs create mode 100644 src/Core/Settings/LoggingSettings/ScimLogLevelSettings.cs create mode 100644 src/Core/Settings/LoggingSettings/SsoLogLevelSettings.cs diff --git a/bitwarden_license/src/Scim/Program.cs b/bitwarden_license/src/Scim/Program.cs index f8d6cb15b031..c0422e594037 100644 --- a/bitwarden_license/src/Scim/Program.cs +++ b/bitwarden_license/src/Scim/Program.cs @@ -1,5 +1,4 @@ using Bit.Core.Utilities; -using Serilog.Events; namespace Bit.Scim { @@ -13,7 +12,7 @@ public static void Main(string[] args) { webBuilder.UseStartup(); webBuilder.ConfigureLogging((hostingContext, logging) => - logging.AddSerilog(hostingContext, e => + logging.AddSerilog(hostingContext, (e, globalSettings) => { var context = e.Properties["SourceContext"].ToString(); @@ -24,7 +23,7 @@ public static void Main(string[] args) return false; } - return e.Level >= LogEventLevel.Warning; + return e.Level >= globalSettings.MinLogLevel.ScimSettings.Default; })); }) .Build() diff --git a/bitwarden_license/src/Sso/Program.cs b/bitwarden_license/src/Sso/Program.cs index 910f09332e90..e1d69faed8aa 100644 --- a/bitwarden_license/src/Sso/Program.cs +++ b/bitwarden_license/src/Sso/Program.cs @@ -1,6 +1,5 @@ using Bit.Core.Utilities; using Serilog; -using Serilog.Events; namespace Bit.Sso { @@ -15,7 +14,7 @@ public static void Main(string[] args) { webBuilder.UseStartup(); webBuilder.ConfigureLogging((hostingContext, logging) => - logging.AddSerilog(hostingContext, e => + logging.AddSerilog(hostingContext, (e, globalSettings) => { var context = e.Properties["SourceContext"].ToString(); if (e.Properties.ContainsKey("RequestPath") && @@ -24,7 +23,7 @@ public static void Main(string[] args) { return false; } - return e.Level >= LogEventLevel.Error; + return e.Level >= globalSettings.MinLogLevel.SsoSettings.Default; })); }) .Build() diff --git a/src/Admin/Program.cs b/src/Admin/Program.cs index d8a55e7b6c63..7dd63033f4c0 100644 --- a/src/Admin/Program.cs +++ b/src/Admin/Program.cs @@ -1,5 +1,4 @@ using Bit.Core.Utilities; -using Serilog.Events; namespace Bit.Admin { @@ -18,7 +17,7 @@ public static void Main(string[] args) }); webBuilder.UseStartup(); webBuilder.ConfigureLogging((hostingContext, logging) => - logging.AddSerilog(hostingContext, e => + logging.AddSerilog(hostingContext, (e, globalSettings) => { var context = e.Properties["SourceContext"].ToString(); if (e.Properties.ContainsKey("RequestPath") && @@ -27,7 +26,7 @@ public static void Main(string[] args) { return false; } - return e.Level >= LogEventLevel.Error; + return e.Level >= globalSettings.MinLogLevel.AdminSettings.Default; })); }) .Build() diff --git a/src/Api/Program.cs b/src/Api/Program.cs index bcd6284af05e..bfc7c9a34179 100644 --- a/src/Api/Program.cs +++ b/src/Api/Program.cs @@ -1,7 +1,6 @@ using AspNetCoreRateLimit; using Bit.Core.Utilities; using Microsoft.IdentityModel.Tokens; -using Serilog.Events; namespace Bit.Api { @@ -16,7 +15,7 @@ public static void Main(string[] args) { webBuilder.UseStartup(); webBuilder.ConfigureLogging((hostingContext, logging) => - logging.AddSerilog(hostingContext, e => + logging.AddSerilog(hostingContext, (e, globalSettings) => { var context = e.Properties["SourceContext"].ToString(); if (e.Exception != null && @@ -26,19 +25,18 @@ public static void Main(string[] args) return false; } - if (e.Level == LogEventLevel.Information && - context.Contains(typeof(IpRateLimitMiddleware).FullName)) + if (context.Contains(typeof(IpRateLimitMiddleware).FullName)) { - return true; + return e.Level >= globalSettings.MinLogLevel.ApiSettings.IpRateLimit; } if (context.Contains("IdentityServer4.Validation.TokenValidator") || context.Contains("IdentityServer4.Validation.TokenRequestValidator")) { - return e.Level > LogEventLevel.Error; + return e.Level >= globalSettings.MinLogLevel.ApiSettings.IdentityToken; } - return e.Level >= LogEventLevel.Error; + return e.Level >= globalSettings.MinLogLevel.ApiSettings.Default; })); }) .Build() diff --git a/src/Billing/Program.cs b/src/Billing/Program.cs index 7b42ad73f978..13e198a58913 100644 --- a/src/Billing/Program.cs +++ b/src/Billing/Program.cs @@ -1,5 +1,4 @@ using Bit.Core.Utilities; -using Serilog.Events; namespace Bit.Billing { @@ -13,13 +12,12 @@ public static void Main(string[] args) { webBuilder.UseStartup(); webBuilder.ConfigureLogging((hostingContext, logging) => - logging.AddSerilog(hostingContext, e => + logging.AddSerilog(hostingContext, (e, globalSettings) => { var context = e.Properties["SourceContext"].ToString(); - if (e.Level == LogEventLevel.Information && - (context.StartsWith("\"Bit.Billing.Jobs") || context.StartsWith("\"Bit.Core.Jobs"))) + if (context.StartsWith("\"Bit.Billing.Jobs") || context.StartsWith("\"Bit.Core.Jobs")) { - return true; + return e.Level >= globalSettings.MinLogLevel.BillingSettings.Jobs; } if (e.Properties.ContainsKey("RequestPath") && @@ -29,7 +27,7 @@ public static void Main(string[] args) return false; } - return e.Level >= LogEventLevel.Warning; + return e.Level >= globalSettings.MinLogLevel.BillingSettings.Default; })); }) .Build() diff --git a/src/Core/OrganizationFeatures/OrganizationServiceCollectionExtensions.cs b/src/Core/OrganizationFeatures/OrganizationServiceCollectionExtensions.cs index 94e59ab31b99..766be30b72c7 100644 --- a/src/Core/OrganizationFeatures/OrganizationServiceCollectionExtensions.cs +++ b/src/Core/OrganizationFeatures/OrganizationServiceCollectionExtensions.cs @@ -12,6 +12,7 @@ using Bit.Core.Tokens; using Microsoft.AspNetCore.DataProtection; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; namespace Bit.Core.OrganizationFeatures { @@ -70,7 +71,8 @@ private static void AddTokenizers(this IServiceCollection services) new DataProtectorTokenFactory( OrganizationSponsorshipOfferTokenable.ClearTextPrefix, OrganizationSponsorshipOfferTokenable.DataProtectorPurpose, - serviceProvider.GetDataProtectionProvider()) + serviceProvider.GetDataProtectionProvider(), + serviceProvider.GetRequiredService>>()) ); } } diff --git a/src/Core/Settings/GlobalSettings.cs b/src/Core/Settings/GlobalSettings.cs index 2b083a7aa36c..88d6996a90c0 100644 --- a/src/Core/Settings/GlobalSettings.cs +++ b/src/Core/Settings/GlobalSettings.cs @@ -1,4 +1,6 @@ -namespace Bit.Core.Settings +using Bit.Core.Settings.LoggingSettings; + +namespace Bit.Core.Settings { public class GlobalSettings : IGlobalSettings { @@ -58,6 +60,7 @@ public virtual string LicenseDirectory public virtual DocumentDbSettings DocumentDb { get; set; } = new DocumentDbSettings(); public virtual SentrySettings Sentry { get; set; } = new SentrySettings(); public virtual SyslogSettings Syslog { get; set; } = new SyslogSettings(); + public virtual ILogLevelSettings MinLogLevel { get; set; } = new LogLevelSettings(); public virtual NotificationHubSettings NotificationHub { get; set; } = new NotificationHubSettings(); public virtual YubicoSettings Yubico { get; set; } = new YubicoSettings(); public virtual DuoSettings Duo { get; set; } = new DuoSettings(); diff --git a/src/Core/Settings/IGlobalSettings.cs b/src/Core/Settings/IGlobalSettings.cs index ec648384e19c..b48f4bd2f1fe 100644 --- a/src/Core/Settings/IGlobalSettings.cs +++ b/src/Core/Settings/IGlobalSettings.cs @@ -15,5 +15,6 @@ public interface IGlobalSettings IBaseServiceUriSettings BaseServiceUri { get; set; } ITwoFactorAuthSettings TwoFactorAuth { get; set; } ISsoSettings Sso { get; set; } + ILogLevelSettings MinLogLevel { get; set; } } } diff --git a/src/Core/Settings/ILogLevelSettings.cs b/src/Core/Settings/ILogLevelSettings.cs new file mode 100644 index 000000000000..648bd863fa4c --- /dev/null +++ b/src/Core/Settings/ILogLevelSettings.cs @@ -0,0 +1,75 @@ +using Serilog.Events; + +namespace Bit.Core.Settings +{ + public interface ILogLevelSettings + { + IBillingLogLevelSettings BillingSettings { get; set; } + IApiLogLevelSettings ApiSettings { get; set; } + IIdentityLogLevelSettings IdentitySettings { get; set; } + IScimLogLevelSettings ScimSettings { get; set; } + ISsoLogLevelSettings SsoSettings { get; set; } + IAdminLogLevelSettings AdminSettings { get; set; } + IEventsLogLevelSettings EventsSettings { get; set; } + IEventsProcessorLogLevelSettings EventsProcessorSettings { get; set; } + IIconsLogLevelSettings IconsSettings { get; set; } + INotificationsLogLevelSettings NotificationsSettings { get; set; } + } + + public interface IBillingLogLevelSettings + { + LogEventLevel Default { get; set; } + LogEventLevel Jobs { get; set; } + } + + public interface IApiLogLevelSettings + { + LogEventLevel Default { get; set; } + LogEventLevel IdentityToken { get; set; } + LogEventLevel IpRateLimit { get; set; } + } + + public interface IIdentityLogLevelSettings + { + LogEventLevel Default { get; set; } + LogEventLevel IdentityToken { get; set; } + LogEventLevel IpRateLimit { get; set; } + } + + public interface IScimLogLevelSettings + { + LogEventLevel Default { get; set; } + } + + public interface ISsoLogLevelSettings + { + LogEventLevel Default { get; set; } + } + + public interface IAdminLogLevelSettings + { + LogEventLevel Default { get; set; } + } + + public interface IEventsLogLevelSettings + { + LogEventLevel Default { get; set; } + LogEventLevel IdentityToken { get; set; } + } + + public interface IEventsProcessorLogLevelSettings + { + LogEventLevel Default { get; set; } + } + + public interface IIconsLogLevelSettings + { + LogEventLevel Default { get; set; } + } + + public interface INotificationsLogLevelSettings + { + LogEventLevel Default { get; set; } + LogEventLevel IdentityToken { get; set; } + } +} diff --git a/src/Core/Settings/LoggingSettings/AdminLogLevelSettings.cs b/src/Core/Settings/LoggingSettings/AdminLogLevelSettings.cs new file mode 100644 index 000000000000..6d8dbf4bf16b --- /dev/null +++ b/src/Core/Settings/LoggingSettings/AdminLogLevelSettings.cs @@ -0,0 +1,10 @@ +using Serilog.Events; + +namespace Bit.Core.Settings.LoggingSettings +{ + public class AdminLogLevelSettings : IAdminLogLevelSettings + { + public LogEventLevel Default { get; set; } = LogEventLevel.Error; + } +} + diff --git a/src/Core/Settings/LoggingSettings/ApiLogLevelSettings.cs b/src/Core/Settings/LoggingSettings/ApiLogLevelSettings.cs new file mode 100644 index 000000000000..902f5291da91 --- /dev/null +++ b/src/Core/Settings/LoggingSettings/ApiLogLevelSettings.cs @@ -0,0 +1,12 @@ +using Serilog.Events; + +namespace Bit.Core.Settings.LoggingSettings +{ + public class ApiLogLevelSettings : IApiLogLevelSettings + { + public LogEventLevel Default { get; set; } = LogEventLevel.Error; + public LogEventLevel IdentityToken { get; set; } = LogEventLevel.Fatal; + public LogEventLevel IpRateLimit { get; set; } = LogEventLevel.Information; + } +} + diff --git a/src/Core/Settings/LoggingSettings/BillingLogLevelSettings.cs b/src/Core/Settings/LoggingSettings/BillingLogLevelSettings.cs new file mode 100644 index 000000000000..af0df2aed9be --- /dev/null +++ b/src/Core/Settings/LoggingSettings/BillingLogLevelSettings.cs @@ -0,0 +1,10 @@ +using Serilog.Events; + +namespace Bit.Core.Settings.LoggingSettings +{ + public class BillingLogLevelSettings : IBillingLogLevelSettings + { + public LogEventLevel Default { get; set; } = LogEventLevel.Warning; + public LogEventLevel Jobs { get; set; } = LogEventLevel.Information; + } +} diff --git a/src/Core/Settings/LoggingSettings/EventsLogLevelSettings.cs b/src/Core/Settings/LoggingSettings/EventsLogLevelSettings.cs new file mode 100644 index 000000000000..d0483d515c35 --- /dev/null +++ b/src/Core/Settings/LoggingSettings/EventsLogLevelSettings.cs @@ -0,0 +1,10 @@ +using Serilog.Events; + +namespace Bit.Core.Settings.LoggingSettings +{ + public class EventsLogLevelSettings : IEventsLogLevelSettings + { + public LogEventLevel Default { get; set; } = LogEventLevel.Error; + public LogEventLevel IdentityToken { get; set; } = LogEventLevel.Fatal; + } +} diff --git a/src/Core/Settings/LoggingSettings/EventsProcessorLogLevelSettings.cs b/src/Core/Settings/LoggingSettings/EventsProcessorLogLevelSettings.cs new file mode 100644 index 000000000000..e8018c24e241 --- /dev/null +++ b/src/Core/Settings/LoggingSettings/EventsProcessorLogLevelSettings.cs @@ -0,0 +1,9 @@ +using Serilog.Events; + +namespace Bit.Core.Settings.LoggingSettings +{ + public class EventsProcessorLogLevelSettings : IEventsProcessorLogLevelSettings + { + public LogEventLevel Default { get; set; } = LogEventLevel.Warning; + } +} diff --git a/src/Core/Settings/LoggingSettings/IconsLogLevelSettings.cs b/src/Core/Settings/LoggingSettings/IconsLogLevelSettings.cs new file mode 100644 index 000000000000..d7940b1c0fb6 --- /dev/null +++ b/src/Core/Settings/LoggingSettings/IconsLogLevelSettings.cs @@ -0,0 +1,9 @@ +using Serilog.Events; + +namespace Bit.Core.Settings.LoggingSettings +{ + public class IconsLogLevelSettings : IIconsLogLevelSettings + { + public LogEventLevel Default { get; set; } = LogEventLevel.Error; + } +} diff --git a/src/Core/Settings/LoggingSettings/IdentityLogLevelSettings.cs b/src/Core/Settings/LoggingSettings/IdentityLogLevelSettings.cs new file mode 100644 index 000000000000..0b8717051dcc --- /dev/null +++ b/src/Core/Settings/LoggingSettings/IdentityLogLevelSettings.cs @@ -0,0 +1,11 @@ +using Serilog.Events; + +namespace Bit.Core.Settings.LoggingSettings +{ + public class IdentityLogLevelSettings : IIdentityLogLevelSettings + { + public LogEventLevel Default { get; set; } = LogEventLevel.Error; + public LogEventLevel IdentityToken { get; set; } = LogEventLevel.Fatal; + public LogEventLevel IpRateLimit { get; set; } = LogEventLevel.Information; + } +} diff --git a/src/Core/Settings/LoggingSettings/LogLevelSettings.cs b/src/Core/Settings/LoggingSettings/LogLevelSettings.cs new file mode 100644 index 000000000000..49947f22ad72 --- /dev/null +++ b/src/Core/Settings/LoggingSettings/LogLevelSettings.cs @@ -0,0 +1,17 @@ + +namespace Bit.Core.Settings.LoggingSettings +{ + public class LogLevelSettings : ILogLevelSettings + { + public IBillingLogLevelSettings BillingSettings { get; set; } = new BillingLogLevelSettings(); + public IApiLogLevelSettings ApiSettings { get; set; } = new ApiLogLevelSettings(); + public IIdentityLogLevelSettings IdentitySettings { get; set; } = new IdentityLogLevelSettings(); + public IScimLogLevelSettings ScimSettings { get; set; } = new ScimLogLevelSettings(); + public ISsoLogLevelSettings SsoSettings { get; set; } = new SsoLogLevelSettings(); + public IAdminLogLevelSettings AdminSettings { get; set; } = new AdminLogLevelSettings(); + public IEventsLogLevelSettings EventsSettings { get; set; } = new EventsLogLevelSettings(); + public IEventsProcessorLogLevelSettings EventsProcessorSettings { get; set; } = new EventsProcessorLogLevelSettings(); + public IIconsLogLevelSettings IconsSettings { get; set; } = new IconsLogLevelSettings(); + public INotificationsLogLevelSettings NotificationsSettings { get; set; } = new NotificationsLogLevelSettings(); + } +} diff --git a/src/Core/Settings/LoggingSettings/NotificationsLogLevelSettings.cs b/src/Core/Settings/LoggingSettings/NotificationsLogLevelSettings.cs new file mode 100644 index 000000000000..339e7c694a47 --- /dev/null +++ b/src/Core/Settings/LoggingSettings/NotificationsLogLevelSettings.cs @@ -0,0 +1,10 @@ +using Serilog.Events; + +namespace Bit.Core.Settings.LoggingSettings +{ + public class NotificationsLogLevelSettings : INotificationsLogLevelSettings + { + public LogEventLevel Default { get; set; } = LogEventLevel.Warning; + public LogEventLevel IdentityToken { get; set; } = LogEventLevel.Fatal; + } +} diff --git a/src/Core/Settings/LoggingSettings/ScimLogLevelSettings.cs b/src/Core/Settings/LoggingSettings/ScimLogLevelSettings.cs new file mode 100644 index 000000000000..c1cba0eb2096 --- /dev/null +++ b/src/Core/Settings/LoggingSettings/ScimLogLevelSettings.cs @@ -0,0 +1,9 @@ +using Serilog.Events; + +namespace Bit.Core.Settings.LoggingSettings +{ + public class ScimLogLevelSettings : IScimLogLevelSettings + { + public LogEventLevel Default { get; set; } = LogEventLevel.Warning; + } +} diff --git a/src/Core/Settings/LoggingSettings/SsoLogLevelSettings.cs b/src/Core/Settings/LoggingSettings/SsoLogLevelSettings.cs new file mode 100644 index 000000000000..fc127c89f8e0 --- /dev/null +++ b/src/Core/Settings/LoggingSettings/SsoLogLevelSettings.cs @@ -0,0 +1,9 @@ +using Serilog.Events; + +namespace Bit.Core.Settings.LoggingSettings +{ + public class SsoLogLevelSettings : ISsoLogLevelSettings + { + public LogEventLevel Default { get; set; } = LogEventLevel.Error; + } +} diff --git a/src/Core/Tokens/DataProtectorTokenFactory.cs b/src/Core/Tokens/DataProtectorTokenFactory.cs index 8029b355475d..ed01e08e0691 100644 --- a/src/Core/Tokens/DataProtectorTokenFactory.cs +++ b/src/Core/Tokens/DataProtectorTokenFactory.cs @@ -1,4 +1,5 @@ using Microsoft.AspNetCore.DataProtection; +using Microsoft.Extensions.Logging; namespace Bit.Core.Tokens { @@ -6,15 +7,17 @@ public class DataProtectorTokenFactory : IDataProtectorTokenFactory where { private readonly IDataProtector _dataProtector; private readonly string _clearTextPrefix; + private readonly ILogger> _logger; - public DataProtectorTokenFactory(string clearTextPrefix, string purpose, IDataProtectionProvider dataProtectionProvider) + public DataProtectorTokenFactory(string clearTextPrefix, string purpose, IDataProtectionProvider dataProtectionProvider, ILogger> logger) { _dataProtector = dataProtectionProvider.CreateProtector(purpose); _clearTextPrefix = clearTextPrefix; + _logger = logger; } public string Protect(T data) => - data.ToToken().ProtectWith(_dataProtector).WithPrefix(_clearTextPrefix).ToString(); + data.ToToken().ProtectWith(_dataProtector, _logger).WithPrefix(_clearTextPrefix).ToString(); /// /// Unprotect token @@ -24,7 +27,7 @@ public string Protect(T data) => /// The parsed tokenable /// Throws CryptographicException if fails to unprotect public T Unprotect(string token) => - Tokenable.FromToken(new Token(token).RemovePrefix(_clearTextPrefix).UnprotectWith(_dataProtector).ToString()); + Tokenable.FromToken(new Token(token).RemovePrefix(_clearTextPrefix).UnprotectWith(_dataProtector, _logger).ToString()); public bool TokenValid(string token) { @@ -45,8 +48,9 @@ public bool TryUnprotect(string token, out T data) data = Unprotect(token); return true; } - catch + catch (Exception ex) { + _logger.LogInformation(ex, "Failed to unprotect token: {rawToken}", token); data = default; return false; } diff --git a/src/Core/Tokens/Token.cs b/src/Core/Tokens/Token.cs index 396b8747d566..356f85b829ab 100644 --- a/src/Core/Tokens/Token.cs +++ b/src/Core/Tokens/Token.cs @@ -1,4 +1,5 @@ using Microsoft.AspNetCore.DataProtection; +using Microsoft.Extensions.Logging; namespace Bit.Core.Tokens { @@ -26,11 +27,27 @@ public Token RemovePrefix(string expectedPrefix) return new Token(_token[expectedPrefix.Length..]); } - public Token ProtectWith(IDataProtector dataProtector) => - new(dataProtector.Protect(ToString())); + public Token ProtectWith(IDataProtector dataProtector, ILogger logger) + { + logger.LogDebug("Protecting token: {token}", this); + return new(dataProtector.Protect(ToString())); + } - public Token UnprotectWith(IDataProtector dataProtector) => - new(dataProtector.Unprotect(ToString())); + public Token UnprotectWith(IDataProtector dataProtector, ILogger logger) + { + var unprotected = ""; + try + { + unprotected = dataProtector.Unprotect(ToString()); + } + catch (Exception e) + { + logger.LogInformation(e, "Failed to unprotect token: {token}", this); + throw; + } + logger.LogDebug("Unprotected token: {token} to {decryptedToken}", this, unprotected); + return new(unprotected); + } public override string ToString() => _token; } diff --git a/src/Core/Utilities/LoggerFactoryExtensions.cs b/src/Core/Utilities/LoggerFactoryExtensions.cs index 98896c56eb34..fae4a9533b34 100644 --- a/src/Core/Utilities/LoggerFactoryExtensions.cs +++ b/src/Core/Utilities/LoggerFactoryExtensions.cs @@ -31,13 +31,17 @@ public static void UseSerilog( public static ILoggingBuilder AddSerilog( this ILoggingBuilder builder, WebHostBuilderContext context, - Func filter = null) + Func filter = null) { if (context.HostingEnvironment.IsDevelopment()) { return builder; } + var globalSettings = new GlobalSettings(); + ConfigurationBinder.Bind(context.Configuration.GetSection("GlobalSettings"), globalSettings); + + bool inclusionPredicate(LogEvent e) { if (filter == null) @@ -49,12 +53,9 @@ bool inclusionPredicate(LogEvent e) { return true; } - return filter(e); + return filter(e, globalSettings); } - var globalSettings = new GlobalSettings(); - ConfigurationBinder.Bind(context.Configuration.GetSection("GlobalSettings"), globalSettings); - var config = new LoggerConfiguration() .Enrich.FromLogContext() .Filter.ByIncludingOnly(inclusionPredicate); diff --git a/src/Events/Program.cs b/src/Events/Program.cs index a6a95646a6b9..25465ef9d254 100644 --- a/src/Events/Program.cs +++ b/src/Events/Program.cs @@ -1,5 +1,4 @@ using Bit.Core.Utilities; -using Serilog.Events; namespace Bit.Events { @@ -14,13 +13,13 @@ public static void Main(string[] args) { webBuilder.UseStartup(); webBuilder.ConfigureLogging((hostingContext, logging) => - logging.AddSerilog(hostingContext, e => + logging.AddSerilog(hostingContext, (e, globalSettings) => { var context = e.Properties["SourceContext"].ToString(); if (context.Contains("IdentityServer4.Validation.TokenValidator") || context.Contains("IdentityServer4.Validation.TokenRequestValidator")) { - return e.Level > LogEventLevel.Error; + return e.Level >= globalSettings.MinLogLevel.EventsSettings.IdentityToken; } if (e.Properties.ContainsKey("RequestPath") && @@ -30,7 +29,7 @@ public static void Main(string[] args) return false; } - return e.Level >= LogEventLevel.Error; + return e.Level >= globalSettings.MinLogLevel.EventsSettings.Default; })); }) .Build() diff --git a/src/EventsProcessor/Program.cs b/src/EventsProcessor/Program.cs index a63c7742c40c..1f5d797d5eb3 100644 --- a/src/EventsProcessor/Program.cs +++ b/src/EventsProcessor/Program.cs @@ -1,5 +1,4 @@ using Bit.Core.Utilities; -using Serilog.Events; namespace Bit.EventsProcessor { @@ -13,7 +12,7 @@ public static void Main(string[] args) { webBuilder.UseStartup(); webBuilder.ConfigureLogging((hostingContext, logging) => - logging.AddSerilog(hostingContext, e => e.Level >= LogEventLevel.Warning)); + logging.AddSerilog(hostingContext, (e, globalSettings) => e.Level >= globalSettings.MinLogLevel.EventsProcessorSettings.Default)); }) .Build() .Run(); diff --git a/src/Icons/Program.cs b/src/Icons/Program.cs index 1f65ea406791..a58a0ccce664 100644 --- a/src/Icons/Program.cs +++ b/src/Icons/Program.cs @@ -1,5 +1,4 @@ using Bit.Core.Utilities; -using Serilog.Events; namespace Bit.Icons { @@ -13,7 +12,7 @@ public static void Main(string[] args) { webBuilder.UseStartup(); webBuilder.ConfigureLogging((hostingContext, logging) => - logging.AddSerilog(hostingContext, e => e.Level >= LogEventLevel.Error)); + logging.AddSerilog(hostingContext, (e, globalSettings) => e.Level >= globalSettings.MinLogLevel.IconsSettings.Default)); }) .Build() .Run(); diff --git a/src/Identity/Program.cs b/src/Identity/Program.cs index 540e3ac75108..848d73420c40 100644 --- a/src/Identity/Program.cs +++ b/src/Identity/Program.cs @@ -1,6 +1,5 @@ using AspNetCoreRateLimit; using Bit.Core.Utilities; -using Serilog.Events; namespace Bit.Identity { @@ -22,22 +21,21 @@ public static IHostBuilder CreateHostBuilder(string[] args) { webBuilder.UseStartup(); webBuilder.ConfigureLogging((hostingContext, logging) => - logging.AddSerilog(hostingContext, e => + logging.AddSerilog(hostingContext, (e, globalSettings) => { var context = e.Properties["SourceContext"].ToString(); - if (context.Contains(typeof(IpRateLimitMiddleware).FullName) && - e.Level == LogEventLevel.Information) + if (context.Contains(typeof(IpRateLimitMiddleware).FullName)) { - return true; + return e.Level >= globalSettings.MinLogLevel.IdentitySettings.IpRateLimit; } if (context.Contains("IdentityServer4.Validation.TokenValidator") || context.Contains("IdentityServer4.Validation.TokenRequestValidator")) { - return e.Level > LogEventLevel.Error; + return e.Level >= globalSettings.MinLogLevel.IdentitySettings.IdentityToken; } - return e.Level >= LogEventLevel.Error; + return e.Level >= globalSettings.MinLogLevel.IdentitySettings.Default; })); }); } diff --git a/src/Notifications/Program.cs b/src/Notifications/Program.cs index 8ea3a5a1b76b..3da5a6d4db5b 100644 --- a/src/Notifications/Program.cs +++ b/src/Notifications/Program.cs @@ -14,13 +14,13 @@ public static void Main(string[] args) { webBuilder.UseStartup(); webBuilder.ConfigureLogging((hostingContext, logging) => - logging.AddSerilog(hostingContext, e => + logging.AddSerilog(hostingContext, (e, globalSettings) => { var context = e.Properties["SourceContext"].ToString(); if (context.Contains("IdentityServer4.Validation.TokenValidator") || context.Contains("IdentityServer4.Validation.TokenRequestValidator")) { - return e.Level > LogEventLevel.Error; + return e.Level >= globalSettings.MinLogLevel.NotificationsSettings.IdentityToken; } if (e.Level == LogEventLevel.Error && @@ -41,7 +41,7 @@ public static void Main(string[] args) return false; } - return e.Level >= LogEventLevel.Warning; + return e.Level >= globalSettings.MinLogLevel.NotificationsSettings.Default; })); }) .Build() diff --git a/src/SharedWeb/Utilities/ServiceCollectionExtensions.cs b/src/SharedWeb/Utilities/ServiceCollectionExtensions.cs index 97cb35cf40bb..489513fe1275 100644 --- a/src/SharedWeb/Utilities/ServiceCollectionExtensions.cs +++ b/src/SharedWeb/Utilities/ServiceCollectionExtensions.cs @@ -35,6 +35,7 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Serilog.Context; using StackExchange.Redis; @@ -116,19 +117,22 @@ public static void AddTokenizers(this IServiceCollection services) new DataProtectorTokenFactory( EmergencyAccessInviteTokenable.ClearTextPrefix, EmergencyAccessInviteTokenable.DataProtectorPurpose, - serviceProvider.GetDataProtectionProvider()) + serviceProvider.GetDataProtectionProvider(), + serviceProvider.GetRequiredService>>()) ); services.AddSingleton>(serviceProvider => new DataProtectorTokenFactory( HCaptchaTokenable.ClearTextPrefix, HCaptchaTokenable.DataProtectorPurpose, - serviceProvider.GetDataProtectionProvider()) + serviceProvider.GetDataProtectionProvider(), + serviceProvider.GetRequiredService>>()) ); services.AddSingleton>(serviceProvider => new DataProtectorTokenFactory( SsoTokenable.ClearTextPrefix, SsoTokenable.DataProtectorPurpose, - serviceProvider.GetDataProtectionProvider())); + serviceProvider.GetDataProtectionProvider(), + serviceProvider.GetRequiredService>>())); } public static void AddDefaultServices(this IServiceCollection services, GlobalSettings globalSettings)