mirror of
https://github.com/rmcrackan/Libation.git
synced 2026-09-13 06:07:30 -04:00
Account.ToString() returned "id - locale", so interpolating an account or
logging a non-destructured {Account} published the address. It now returns
the masked entry, with a DebuggerDisplay keeping the real values visible
while debugging. Nothing in the UI relied on it: both scan dialogs build
their own labels.
For structured logging, an ILogMasked type is reduced to its masked entry
by a destructuring policy, which covers the {@DebugInfo} shape most of
Libation's logging uses. And DecryptKey - the activation bytes - is now a
SecretString, so it has no plaintext for a reflective dump to find at all.
Its JSON stays the bare string it always was, so existing settings files
load unchanged.
A registered policy that nobody notices is missing protects nothing, so
the tests write through a logger built by ConfigureLogging itself rather
than a hand-made one. Deleting either registration fails them: the masked
object comes out whole, and a destructured secret renders as
{"HasValue":true} instead of its length.
The contribute guide now states the rule, since the reason for all of
this is invisible from the code alone: log files get attached to public
issues, so treat what goes in them as published.
Co-authored-by: rmcrackan <rmcrackan@gmail.com>
38 lines
1.2 KiB
C#
38 lines
1.2 KiB
C#
using Serilog.Core;
|
|
using Serilog.Events;
|
|
|
|
namespace LibationFileManager;
|
|
|
|
/// <summary>
|
|
/// Implemented by types that identify something private, and so must appear in a log only in masked form.
|
|
/// </summary>
|
|
public interface ILogMasked
|
|
{
|
|
/// <summary>The only form of this object that may reach a log file.</summary>
|
|
string MaskedLogEntry { get; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Reduces any <see cref="ILogMasked"/> to its masked entry when Serilog destructures it, so that a structured
|
|
/// log call - <c>{@Account}</c>, or an anonymous <c>{@DebugInfo}</c> object holding one - cannot publish the
|
|
/// unmasked object by accident.
|
|
/// <para>
|
|
/// This covers Serilog's own destructuring only. Serilog.Exceptions flattens a logged exception's properties
|
|
/// itself before Serilog sees them, so an exception must not carry one of these in the first place.
|
|
/// </para>
|
|
/// </summary>
|
|
public class MaskedLogEntryPolicy : IDestructuringPolicy
|
|
{
|
|
public bool TryDestructure(object value, ILogEventPropertyValueFactory propertyValueFactory, out LogEventPropertyValue result)
|
|
{
|
|
if (value is ILogMasked masked)
|
|
{
|
|
result = new ScalarValue(masked.MaskedLogEntry);
|
|
return true;
|
|
}
|
|
|
|
result = null!;
|
|
return false;
|
|
}
|
|
}
|