From e8910fab8af95a0f7ec98831c8507694792e2e5a Mon Sep 17 00:00:00 2001 From: Rolf Kristensen Date: Sat, 10 Sep 2022 14:34:28 +0200 Subject: [PATCH] EcsJsonConfiguration - With converters to protect against bad types --- .../Serialization/JsonConfiguration.cs | 25 +++++++++++++-- .../MessageTests.cs | 31 +++++++++++++++++++ 2 files changed, 54 insertions(+), 2 deletions(-) diff --git a/src/Elastic.CommonSchema/Serialization/JsonConfiguration.cs b/src/Elastic.CommonSchema/Serialization/JsonConfiguration.cs index b1353720..c63f8b22 100644 --- a/src/Elastic.CommonSchema/Serialization/JsonConfiguration.cs +++ b/src/Elastic.CommonSchema/Serialization/JsonConfiguration.cs @@ -18,14 +18,35 @@ public static class EcsJsonConfiguration PropertyNamingPolicy = new SnakeCaseJsonNamingPolicy(), Converters = { - new EcsDocumentJsonConverterFactory() + new EcsDocumentJsonConverterFactory(), + new EcsJsonStringConverter(), // Cannot transfer assembly-objects over the wire + new EcsJsonStringConverter(), // Cannot transfer module-objects over the wire + new EcsJsonStringConverter(), // Cannot transfer method-addresses over the wire + new EcsJsonStringConverter(), // Cannot transfer methods over the wire + new EcsJsonStringConverter(), // Cannot transfer types over the wire + new EcsJsonStringConverter(), // Cannot transfer Dictionary-Comparer over the wire + new EcsJsonStringConverter(), // Stream-properties often throws exceptions }, - }; internal static readonly JsonConverter DateTimeOffsetConverter = (JsonConverter)SerializerOptions.GetConverter(typeof(DateTimeOffset)); public static readonly EcsDocumentJsonConverter DefaultEcsDocumentJsonConverter = new(); + + private sealed class EcsJsonStringConverter : JsonConverter + { + public override bool CanConvert(Type typeToConvert) => typeof(T).IsAssignableFrom(typeToConvert); + + public override T Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) => default; + + public override void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions options) + { + if (value is null) + writer.WriteNullValue(); + else + writer.WriteStringValue(value.ToString()); + } + } } } diff --git a/tests/Elastic.CommonSchema.NLog.Tests/MessageTests.cs b/tests/Elastic.CommonSchema.NLog.Tests/MessageTests.cs index e9755b3e..d15b781f 100644 --- a/tests/Elastic.CommonSchema.NLog.Tests/MessageTests.cs +++ b/tests/Elastic.CommonSchema.NLog.Tests/MessageTests.cs @@ -49,6 +49,37 @@ public void SeesMessageWithProp() => TestLogger((logger, getLogEvents) => y.Should().HaveValue().And.Be(2.2); }); + [Fact] + public void SeesMessageWithEvilProp() => TestLogger((logger, getLogEvents) => + { + logger.Info("Info {EvilValue}", new BadObject()); + + var logEvents = getLogEvents(); + logEvents.Should().HaveCount(1); + + var ecsEvents = ToEcsEvents(logEvents); + + var (_, info) = ecsEvents.First(); + info.Message.Should().Be("Info Elastic.CommonSchema.NLog.Tests.MessageTests+BadObject"); + info.Metadata.Should().ContainKey("EvilValue"); + + var x = info.Metadata["EvilValue"] as System.Collections.Generic.Dictionary; + x.Should().NotBeNull().And.NotBeEmpty(); + }); + + class BadObject + { + // public IEnumerable Recursive => new List(new[] { "Hello", (object)this }) + + // public string EvilProperty => throw new NotSupportedException() + + public System.Type TypeProperty { get; } = typeof(BadObject); + + public System.Reflection.MethodInfo MethodInfoProperty { get; } = typeof(BadObject).GetProperty(nameof(MethodInfoProperty)).GetMethod; + + public System.Action DelegateProperty { get; } = new System.Action(() => throw new NotSupportedException()); + } + [Fact] public void SeesMessageWithException() => TestLogger((logger, getLogEvents) => {