buehler/dotnet-operator-sdk

[bug]: Mutating WebHook is throwing a Json exception

EdwardCooke opened this issue · 4 comments

Describe the bug

With the latest version the mutating webhook doesn't get called correctly.

Here's the error that it is returning

fail: Microsoft.AspNetCore.Server.Kestrel[13]
      Connection id "0HMOES899AHEL", Request id "0HMOES899AHEL:0000000B": An unhandled exception was thrown by the application.
      System.Text.Json.JsonException: 'M' is an invalid start of a value. Path: $ | LineNumber: 0 | BytePositionInLine: 0.
       ---> System.Text.Json.JsonReaderException: 'M' is an invalid start of a value. LineNumber: 0 | BytePositionInLine: 0.
         at System.Text.Json.ThrowHelper.ThrowJsonReaderException(Utf8JsonReader& json, ExceptionResource resource, Byte nextByte, ReadOnlySpan`1 bytes)
         at System.Text.Json.Utf8JsonReader.ConsumeValue(Byte marker)
         at System.Text.Json.Utf8JsonReader.ReadFirstToken(Byte first)
         at System.Text.Json.Utf8JsonReader.ReadSingleSegment()
         at System.Text.Json.Utf8JsonReader.Read()
         at System.Text.Json.Serialization.JsonConverter`1.ReadCore(Utf8JsonReader& reader, JsonSerializerOptions options, ReadStack& state)
         --- End of inner exception stack trace ---
         at System.Text.Json.ThrowHelper.ReThrowWithPath(ReadStack& state, JsonReaderException ex)
         at System.Text.Json.Serialization.JsonConverter`1.ReadCore(Utf8JsonReader& reader, JsonSerializerOptions options, ReadStack& state)
         at System.Text.Json.JsonSerializer.ReadFromSpan[TValue](ReadOnlySpan`1 utf8Json, JsonTypeInfo jsonTypeInfo, Nullable`1 actualByteCount)
         at System.Text.Json.JsonSerializer.ReadFromSpan[TValue](ReadOnlySpan`1 json, JsonTypeInfo jsonTypeInfo)
         at System.Text.Json.JsonSerializer.Deserialize[TValue](String json, JsonSerializerOptions options)
         at k8s.KubernetesJson.Deserialize[TValue](String json)
         at KubeOps.Operator.Webhooks.IAdmissionWebhook`2.<Register>b__15_0(HttpContext context)
         at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
         at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ProcessRequests[TContext](IHttpApplication`1 application)

I have narrowed it down to

var review = KubernetesJson.Deserialize<AdmissionReview<TEntity>>(context.Request.Body.ToString());

It is calling ToString on the body stream. This returns the type name, not the actual content of the stream.

To reproduce

Use the template,
Create a mutating webhook for a pod
Deploy
Create a pod

Expected behavior

Not to throw the error and allow the mutating webhook to work

Screenshots

No response

Additional Context

I also had to modify the resulting dockerfile to reference the 6.0 docker images instead of latest.

Hi. We are also hitting a similar issue, but with a Validating web hook. Could this be caused by this change, please? In this release the Newtonsoft.Json package was replaced with System.Text.Json.
Which version of KubeOps are you using @EdwardCooke, please?

Maybe that 'M' stands for Microsoft.AspNetCore.WebUtilities.FileBufferingReadStream which is returned from the ToString() method.

Is it possible that this change caused this issue? A StreamReader was changed into:

var review = KubernetesJson.Deserialize<AdmissionReview<TEntity>>(context.Request.Body.ToString());

In this case it could be fixed by using one of the Read... methods of the Stream instead of ToString()

Yes and thanks @anekdoti I will create a PR with the following fix:

using var reader = new StreamReader(context.Request.Body);

var requestBody = await reader.ReadToEndAsync();

var review = KubernetesJson.Deserialize<AdmissionReview<TEntity>>(requestBody);