I have created a custom model binder for my webhook. When I subscribe to the webhook the validation works correctly, but when it receives a ResourceWriteSuccessEvent or a ResourceDeleteSuccessEvent type I get the following error when passing the json string into the eventGridSubscriber.DeserializeEventGridEvents method,
Newtonsoft.Json.JsonReaderException HResult=0x80131500 Message=Error reading string. Unexpected token: StartObject. Path 'authorization'. Source=Newtonsoft.Json StackTrace: at Newtonsoft.Json.JsonReader.ReadAsString() at Newtonsoft.Json.JsonReader.ReadForType(JsonContract contract, Boolean hasConverter) at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateObject(Object newObject, JsonReader reader, JsonObjectContract contract, JsonProperty member, String id) at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue) at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue) at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType, Boolean checkAdditionalContent) at Newtonsoft.Json.JsonSerializer.DeserializeInternal(JsonReader reader, Type objectType) at Newtonsoft.Json.Linq.JToken.ToObject(Type objectType, JsonSerializer jsonSerializer) at Microsoft.Azure.EventGrid.EventGridSubscriber.DeserializeEventGridEventData(EventGridEvent[] eventGridEvents, JsonSerializer jsonSerializer) at Microsoft.Azure.EventGrid.EventGridSubscriber.DeserializeEventGridEvents(String requestContent, JsonSerializer jsonSerializer) at Microsoft.Azure.EventGrid.EventGridSubscriber.DeserializeEventGridEvents(String requestContent)
I have tried to implement a custom model instead of using ResourceWriteSuccessData but get the same result.
My model binder looks like this,
public class EventGridEventModelBinder : IModelBinder
{
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
controllerContext.HttpContext.Request.InputStream.Position = 0;
using (var sr = new StreamReader(controllerContext.HttpContext.Request.InputStream))
{
var json = sr.ReadToEnd();
EventGridSubscriber eventGridSubscriber = new EventGridSubscriber();
eventGridSubscriber.AddOrUpdateCustomEventMapping(EventTypes.EventGridSubscriptionValidationEvent, typeof(SubscriptionValidationEventData));
eventGridSubscriber.AddOrUpdateCustomEventMapping(EventTypes.ResourceWriteSuccessEvent, typeof(ResourceWriteSuccessData));
eventGridSubscriber.AddOrUpdateCustomEventMapping(EventTypes.ResourceDeleteSuccessEvent, typeof(ResourceDeleteSuccessData));
return eventGridSubscriber.DeserializeEventGridEvents(json);
}
}
}
The test json im sending through is,
[
{
"subject":"/subscriptions/{subscription-id}/resourcegroups/{resource-group}/providers/Microsoft.Storage/storageAccounts/{storage-name}",
"eventType":"Microsoft.Resources.ResourceWriteSuccess",
"eventTime":"2018-07-19T18:38:04.6117357Z",
"id":"4db48cba-50a2-455a-93b4-de41a3b5b7f6",
"data":{
"authorization":{
"scope":"/subscriptions/{subscription-id}/resourcegroups/{resource-group}/providers/Microsoft.Storage/storageAccounts/{storage-name}",
"action":"Microsoft.Storage/storageAccounts/write",
"evidence":{
"role":"Subscription Admin"
}
},
"claims":{
"aud":"{audience-claim}",
"iss":"{issuer-claim}",
"iat":"{issued-at-claim}",
"nbf":"{not-before-claim}",
"exp":"{expiration-claim}",
"_claim_names":"{\"groups\":\"src1\"}",
"_claim_sources":"{\"src1\":{\"endpoint\":\"{URI}\"}}",
"http://schemas.microsoft.com/claims/authnclassreference":"1",
"aio":"{token}",
"http://schemas.microsoft.com/claims/authnmethodsreferences":"rsa,mfa",
"appid":"{ID}",
"appidacr":"2",
"http://schemas.microsoft.com/2012/01/devicecontext/claims/identifier":"{ID}",
"e_exp":"{expiration}",
"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname":"{last-name}",
"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname":"{first-name}",
"ipaddr":"{IP-address}",
"name":"{full-name}",
"http://schemas.microsoft.com/identity/claims/objectidentifier":"{ID}",
"onprem_sid":"{ID}",
"puid":"{ID}",
"http://schemas.microsoft.com/identity/claims/scope":"user_impersonation",
"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier":"{ID}",
"http://schemas.microsoft.com/identity/claims/tenantid":"{ID}",
"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name":"{user-name}",
"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn":"{user-name}",
"uti":"{ID}",
"ver":"1.0"
},
"correlationId":"{ID}",
"resourceProvider":"Microsoft.Storage",
"resourceUri":"/subscriptions/{subscription-id}/resourcegroups/{resource-group}/providers/Microsoft.Storage/storageAccounts/{storage-name}",
"operationName":"Microsoft.Storage/storageAccounts/write",
"status":"Succeeded",
"subscriptionId":"{subscription-id}",
"tenantId":"{tenant-id}"
},
"dataVersion":"2",
"metadataVersion":"1",
"topic":"/subscriptions/{subscription-id}/resourceGroups/{resource-group}"
}
]
This is the custom model I have tried
`public class ResourceWriteSuccessDataCustom
{
[JsonProperty("authorization")]
public Authorization Authorization { get; set; }
[JsonProperty("subscriptionId")]
public string SubscriptionId { get; set; }
[JsonProperty("tenantId")]
public string TenantId { get; set; }
}
public class Authorization
{
[JsonProperty("scope")]
public string Scope { get; set; }
[JsonProperty("action")]
public string Action { get; set; }
[JsonProperty("evidence")]
public Evidence Evidence { get; set; }
}
public class Evidence
{
[JsonProperty("role")]
public string Role { get; set; }
}
Update The original issue has already been raised as a bug for the nuget package https://github.com/Azure/azure-sdk-for-net/issues/5189
I still doesn't explain why my custom model isn't working.
I ended up removing all of the EventGridSubscriber as there was too many bugs and used the standard JSON deserialize object method instead.
JsonConvert.DeserializeObject<EventGridEvent[]>(json);
User contributions licensed under CC BY-SA 3.0