Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Exception on importing settings from appsettings.json on version 1.7.1 #25

Closed
alexandries98 opened this issue Feb 6, 2023 · 11 comments
Closed

Comments

@alexandries98
Copy link

Hello,

I was trying to use the new functionality of adding MaskingOperators from appsetings.json, but I am getting this exception:

System.InvalidOperationException: 'Cannot create instance of type 'Serilog.Enrichers.Sensitive.SensitiveDataEnricherOptions' because it is missing a public parameterless constructor.'

image

At first, I thought that I made a bad configuration on MaskingOperators, but if I delete it from json and use only MaskValue and MaskProperties, the behavior remains the same, throwing the exception.

.UseSerilog((_, _, configuration) => configuration
            .ReadFrom.Configuration(builder.Configuration));
"Serilog": {
    "Using": [     
      "Serilog.Enrichers.Sensitive"
    ],
    "Enrich": [
      {
        "Name": "WithSensitiveDataMasking",
        "Args": {
          "options": {
            "MaskValue": "**SECRET**",
            "MaskProperties": [ "secret" ],
            "MaskingOperators": [ "SerilogPOC.API.LoggingMasks.CustomSecretMaskingOperator, API" ]
          }
        }
      }
    ]
  }

However, in version 1.7.0 the exception is not happening and things work as expected.

Thank you! 😄

@SViradiya-MarutiTech
Copy link

I think there is some issue in namespace,. can you check calling constructor?

@sandermvanvliet
Copy link
Contributor

Here's a repro test case I just made and that seems to work fine:

    [Fact]
    public void ReproCaseIssue25()
    {
        const string jsonConfiguration = @"
{
  ""Serilog"": {
    ""Using"": [
      ""Serilog.Enrichers.Sensitive""
    ],
    ""Enrich"": [
      {
        ""Name"": ""WithSensitiveDataMasking"",
        ""Args"": {
          ""options"": {
            ""MaskValue"": ""**SECRET**"",
            ""MaskProperties"": [
              ""secret""
            ]
          }
        }
      }
    ]
  }
}";

        var memoryStream = new MemoryStream();
        memoryStream.Write(Encoding.UTF8.GetBytes(jsonConfiguration));
        memoryStream.Seek(0, SeekOrigin.Begin);

        var configuration = new ConfigurationBuilder()
            .AddJsonStream(memoryStream)
            .Build();

        var inMemorySink = new InMemorySink();

        var logger = new LoggerConfiguration()
            .ReadFrom.Configuration(configuration)
            .WriteTo.Sink(inMemorySink)
            .CreateLogger();

        logger.Information("A test message {secret}", "this is secret");

        inMemorySink
            .Should()
            .HaveMessage("A test message {secret}")
            .Appearing().Once()
            .WithProperty("secret")
            .WithValue("**SECRET**");
    }

If you can provide a simple console app that reproduces the problem I'm happy to have a look but with what you've supplied it all seems to work fine.

@popolony2k
Copy link

popolony2k commented Feb 14, 2023

Here's a repro test case I just made and that seems to work fine:

    [Fact]
    public void ReproCaseIssue25()
    {
        const string jsonConfiguration = @"
{
  ""Serilog"": {
    ""Using"": [
      ""Serilog.Enrichers.Sensitive""
    ],
    ""Enrich"": [
      {
        ""Name"": ""WithSensitiveDataMasking"",
        ""Args"": {
          ""options"": {
            ""MaskValue"": ""**SECRET**"",
            ""MaskProperties"": [
              ""secret""
            ]
          }
        }
      }
    ]
  }
}";

        var memoryStream = new MemoryStream();
        memoryStream.Write(Encoding.UTF8.GetBytes(jsonConfiguration));
        memoryStream.Seek(0, SeekOrigin.Begin);

        var configuration = new ConfigurationBuilder()
            .AddJsonStream(memoryStream)
            .Build();

        var inMemorySink = new InMemorySink();

        var logger = new LoggerConfiguration()
            .ReadFrom.Configuration(configuration)
            .WriteTo.Sink(inMemorySink)
            .CreateLogger();

        logger.Information("A test message {secret}", "this is secret");

        inMemorySink
            .Should()
            .HaveMessage("A test message {secret}")
            .Appearing().Once()
            .WithProperty("secret")
            .WithValue("**SECRET**");
    }

If you can provide a simple console app that reproduces the problem I'm happy to have a look but with what you've supplied it all seems to work fine.

Hi friend.

I'm using your code and I'm facing the same issue @alexandries98 has reported before.

Below I'm attaching the image with exception, running your code (The version I'm using, is 1.7.1)

image

@popolony2k
Copy link

popolony2k commented Feb 14, 2023

I think the reason isn't working anymore is because you changed SensitiveDataEnricherOptions in 1.7.1 to a new implementation with default parameters and internally maybe the injection dependency mechanism doesn't know how to deal with this constructor, because in version 1.7.0 there was no constructors, so when don't implement a constructor in C# it consider an implicit consctuctor with no parameters and for this reason it can deal with a "no parameter" constructor.
Check images 1.7.0 and 1.7.1 below with decompiled code of both versions.

1.7.0 (With implicit default constructor (no parameter)

image

1.7.1 (With the new constrcutor with all parameters with default values)

image

@SViradiya-MarutiTech
Copy link

@popolony2k Did you find solution?

@sandermvanvliet
Copy link
Contributor

It's interesting that the unit test (which is on the latest commit) works while a repro application fails.

@sandermvanvliet
Copy link
Contributor

I've found the problem and also why I wasn't able to reproduce it at first.

If the Microsoft.Extensions.Configuration.Binder package is installed in your project it works fine. When it's not present you get the error as reported.

I'm checking why this is the case because it's not very intuitive.

@sandermvanvliet
Copy link
Contributor

sandermvanvliet commented Mar 4, 2023

@SViradiya-MarutiTech @popolony2k in the meantime a workaround is to install Microsoft.Extensions.Configuration.Binder and it'll work without any additional configuration or code change required.

@sandermvanvliet
Copy link
Contributor

More specifically you need version ... or higher. It was actually introduced in this commit: dotnet/runtime@d78f364

Serilog.Settings.Configuration uses version 2.0,0 of the binder package which doesn't support types with a "complex" constructor and that's what is triggering this issue.

sandermvanvliet added a commit that referenced this issue Mar 4, 2023
… 7.0.0 or up was required for JSON configuration to work
@sandermvanvliet
Copy link
Contributor

sandermvanvliet commented Mar 4, 2023

Ok this is "fixed" in release 1.7.2

However... configuring which masking operators to use has changed slightly. Instead of setting MaskingOperators in your JSON config you will need to use Operators.
The Serilog.Settings.Configuration package does not know how to handle collections of custom types (or at least, I haven't been able to get it to work at all) so there is now a workaround that actually works.

If you have a custom masking operator that requires configuration through a constructor parameter, that won't work and you will have to configure via code instead.

@sandermvanvliet
Copy link
Contributor

@alexandries98 ☝️

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants