Eventos con dos visiones, consumidor y publicador
Si recordamos el principal objetivo de Event Grid como servicio serverless, es "facilitar" la conectividad entre sistemas mediante una compleja arquitectura de Eventos.
Recodemos que en Event Grid tenemos que poner foco en el "cómo se publica", y en el cómo se "consume" un evento.
Un publicador de eventos o desde este momento un "origen del evento", genera un mensaje o evento en un Topic, al cual tenemos suscriptos muchos controladores de eventos como pueden ser una Azure Function, una Logic App, un Services Bus o un Webhook personalizado de nuestro sistema.
Event Grid nos proporcionaba todas las herramientas necesarias para asegurar el evento al Topic, y su posterior recepción en el controlador de eventos o handler, pero ¿Cómo gobernamos quien consume nuestros eventos? ¿Puedo separar esta relación entre el publicador y el consumidor?
Todo esto lo vamos a conseguir con Event Grid Partner, que se centra en esa relación entre el suscriptor y el publicador, para hacerla mucho más amigable.
¿Qué es Event Grid Partner?
Event Grid Partner es una nueva "característica" de Event Grid, que actualmente está en preview y que nos permite publicar nuestros catálogos de eventos como si fuéramos un SaaS de terceros, con la concreta idea de que los sistemas que van a consumir estos eventos no tienen por qué conocer nada de la arquitectura de nuestros publicadores.
Es decir, yo publico mis eventos en un único Topic o Tema Asociado en este caso, al cual se van a suscribir mis consumidores, sin tener conocimiento alguno de que hay por debajo, cosa que facilita mucho sobre todo al consumidor, pero también al publicador.
Como publicador, esta nueva característica nos permite tener nuestros eventos disponibles en Azure de forma global. Los usuarios podrán filtrar además estos eventos y enrutarlos mediante el uso de temas asociados, desde las suscripciones que son propiedad del "consumidor", y nunca del publicador. En resumen, permite separar de forma limpia la propiedad, administración y la facturación de los recursos de los temas asociados, entre los publicadores y los suscriptores.
Como consumidor, vamos a recibir muchos más eventos, de estos SaaS que no son de propiedad del consumidor, pero a los cuales vamos a poder conectar nuestros sistemas, o lo que es lo mismo podemos conectar por ejemplo servicios serverless como puede ser un Azure Functions de nuestra suscripción, con un evento producido en la suscripción de un cliente, o de un producto final como a futuro puede ser un SharePoint, un Dynamics 365 o incluso de otros vendor como podría ser una aplicación en Amazon Web Services.
¿Cómo funciona Event Grid Partner? ¿Cómo es el proceso de publicación?
Para poder profundizar un poco más en esta nueva funcionalidad de Event Grid, necesitamos conocer bien la arquitectura del servicio, y sobre todo el proceso de suscripción a un evento.
Vale la pena recordar que tenemos las siguientes peculiaridades:
Los eventos los vamos a publicar al mundo, de forma global dentro de Azure, lo cual nuestra idea es que cualquiera desde el Marketplace pueda llegar a esos eventos.
Tenemos que asegurarnos de hacer una publicación limpia y muy informada, ya que nuestros consumidores no les interesa conocer el mecanismo de publicación de un evento, pero si conocer los datos que van a recibir, que tipos de Topics pueden consumir desde sus Handlers, y en consecuencia montar los mejores procesos posibles en real time.
La trasmisión del mensaje de un evento para Event Grid Partner se hace mediante el schema CloudEvents, y no con el schema anterior de Event Grid. Tiene sentido ya que CloudEvents se está convirtiendo en un estándar de eventos como puede ser Open API en las API Rest.
Todos los eventos los recoge el "consumidor" en un único Topic, o lo que es lo mismo en una misma URL de Topic, donde podrá añadir las suscripciones necesarias, los filtros y los enrutamientos.
Una vez aclarado estos puntos clave, podemos empezar a "explicar el proceso de suscripción" a un evento asociado de Event Grid, y las piezas que tiene el sistema.
Como vemos en la figura anterior, por parte del "publicador tenemos las siguientes piezas":
Este paso al estar todavía el proceso en preview, requiere de una "aprobación" por parte de Microsoft, que podemos obtener en el siguiente enlace. Este paso es global y no está asociado a ninguna región de Azure en concreto. Al crear hoy en día desde el portal de Azure el registro de nuestro Partner evento, tendremos un resultado muy similar al de la siguiente imagen.
Un namespace está siempre vinculado a un Partner, y en la práctica podemos tener más de uno por Partner. Como vemos en la siguiente imagen, esto nos recuerda muy mucho a "un Domain", en Event Grid, ya que nos permite centralizar en una URL los eventos de nuestro sistema.
Si revisamos la imagen anterior, podemos ver que un "Namespace", en mi caso tiene 3 Canales para añadir, borrar y editar un elemento de mi catálogo de eventos. Esto nos recuerda mucho a la agrupación de Topics en un "Event Domain" de Event Grid.
Donde antes teníamos un "conjunto" de topics, ahora tenemos un conjunto de "channels" asociados a un namespace, desde el cual con una única URL podemos centralizar todos los eventos, a los cuales se van a suscribir nuestros clientes.
La diferencia es que a este Topic no se le puede mandar eventos de forma manual como hacíamos con un "Custom Topic", si no que siempre los envía el Namespace vía el canal correspondiente.
Podemos decir ahora revisando la figura siguiente, que un cliente se va a suscribir a un "Channel" determinado, desde el cual tendrá un topic y enrutados los eventos que nosotros decidamos enviar desde el Namespace.
Consumiendo eventos de terceros, Auth0
Para probar esta funcionalidad, la forma más directa es "consumir" el primer SaaS que se ha subido al carro de los Partners Events. En este caso podemos conectarnos a los eventos de Auth0, una conocida plataforma para gestionar las identidades de tus aplicaciones y 100% disponible en modo SaaS.
Para empezar a utilizar estos eventos necesitamos:
Crear una licencia trial de Auth0, desde la cual podemos empezar hacer nuestras pruebas (Sign Up - Auth0)
Crear un Event Grid partner Topic de Auth0 y para ello podemos desde el portal de Azure seguir los siguientes pasos:
Buscar en el market place la opción "Event Grid Partner Topic" y darle a Crear.
Nos llevará al listado de Partner, que ahora mismo solo cuenta con Auth0, pero en el cual pueden estar tus eventos si sigues el proceso de publicación que hemos visto antes. Seleccionamos el Topic de Auth0, y empezamos a crear la conexión entre Azure y Auth0
El paso de creación de la suscripción y por tanto la creación del Topic a Auth0 se hace 100% desde el portal propio de Auth0, y podremos acceder desde el enlace "To Auth0 website", que vemos en la imagen anterior.
Los pasos a seguir los tenemos en el siguiente enlace Stream Logs to Azure Event Grid (auth0.com), y en resumen nos crea un Stream de datos entre Event Grid y el Partner de Auth0 como vemos en la siguiente imagen.
Todo esto del lado de Auth0, del lado de Azure observaremos que en la suscripción que hayamos escogido nos creará un "Topic", en el cual Auth0 dejará todos los eventos de su sistema (listado eventos), y al cual podremos añadir una suscripción de un webhook nuestro, como por ejemplo podría ser un Azure Functions.
Desde este momento, Auth0 enviará siempre un evento con un schema CloudEvent cada vez que suceda algo en nuestra cuenta de Auth0 relacionado con uno de los muchos eventos existentes, como el siguiente:
1{2"specversion": "1.0",3"id": "90020200430183047601000053476708863112207860729269714946",4"source": "urn:uuid:184d388d-16f3-4c1f-8bdb-35afc787cd12",5"type": "com.auth0.Log",6"datacontenttype": "application/json",7"data": {8"date": "2020-01-29T17:26:50.193Z",9"type": "sapi",10"description": "Create a log stream",11 "client_id": "",12 "client_name": "",13 "ip": "",14 "user_id": "",15"log_id":16"90020200430183047601000053476708863112207860729269714946"17}18}19
Consumiendo nuestros Eventos CloudEvents con Azure Functions y desde Auth0
El último paso que tenemos que trabajar,es en el "suscribir" nuestros webhook, en este caso un Azure Functions a nuestro Topic de Event Grid Partner. Para ello lo primero es entender que como vamos a usar CloudEvents, no podemos usar los Triggers de Event Grid para Azure Functions, ya que no entendería el mensaje que manda Auth0, y debemos crear una function con un HTTP trigger.
El código va a ser muy estándar, y lo único que debemos tener en cuenta es:
1if (req.Method == HttpMethod.Options)23{45// If the request is for subscription validation, send back the6validation code78var response = req.CreateResponse(HttpStatusCode.OK);910response.Headers.Add("Webhook-Allowed-Origin",11"eventgrid.azure.net");12return response;13}14
1var requestmessage = await req.Content.ReadAsStringAsync();23var message = JToken.Parse(requestmessage);45// The request isn't for subscription validation, so it's for an event.67// CloudEvents schema delivers one event at a time.89log.LogInformation($"Source: {message["source"]}");1011log.LogInformation($"Time: {message["eventTime"]}");1213log.LogInformation($"Event data: {message["data"]}");14
El Código completo de nuestra Función es el siguiente:
1public static class AuthHandlerCustomPartnerTopic2{3static readonly HttpClient client = new HttpClient();45[FunctionName("AuthHandlerCustomPartnerTopic")]6public static async Task<HttpResponseMessage> Run(7[HttpTrigger(AuthorizationLevel.Function, "post",8"options","get", Route = null)] HttpRequestMessage req,9ILogger log)10{11log.LogInformation("C# HTTP trigger function processed a request.");12if (req.Method == HttpMethod.Options)13{14// If the request is for subscription validation, send back the validation code15var response = req.CreateResponse(HttpStatusCode.OK);16response.Headers.Add("Webhook-Allowed-Origin",17"eventgrid.azure.net");18return response;19}2021var requestmessage = await req.Content.ReadAsStringAsync();22var message = JToken.Parse(requestmessage);23log.LogInformation($"Source: {message["source"]}");24log.LogInformation($"Time: {message["eventTime"]}");25log.LogInformation($"Event data: {message["data"]}");26return req.CreateResponse(request.StatusCode);27}28}29}30
Si publicamos esta función en Azure, y accedemos al Topic que se nos ha generado desde Auth0, podremos añadir una nueva "suscripción", y escogeremos en este caso un webhook con la URL de nuestra Azure Functions, ya que por el mismo motivo que hemos visto en el código, al ser un schema CloudEvents no nos deja elegir un Azure Functions en el portal.
Si todo ha ido de forma correcta nos debe aparecer la suscripción en el listado inferior de la página Overview de nuestro Topic. Si accedemos a la suscripción comprobaremos que es como cualquier otra suscripción a un Topic, y podremos aplicar enrutamiento, filtros o seguridad a la misma.
Por último, para probar que todo funciona correctamente, abrimos la consola de nuestra Azure Functions por un lado y accedemos a nuestra cuenta de Auth0, y en la propia Home se nos ofrecerá hacer una prueba del servicio, y en concreto un formulario de login.
Si por ejemplo hacemos la prueba y el resultado de login es "erroneo", se generará un evento de login, con el detalle del error, y lo recepcionará nuestra Azure Function.
El servicio avanza y no hay quien lo pare
Bueno pues el titular lo dice todo, esto no para, y si bien muchos pensarían que esto de Event Grid es para otros, o para arquitecturas complejas, no es así para nada. Cada vez tenemos más escenarios de ejecución, y no solo referidos a complejas arquitecturas EDA, donde requiere un coste y una inversión muy alta en servicios como Service Bus entre otros.
Esta nueva visión de que SaaS de los que no somos propietarios, nos dejen en tiempo real un catálogo de eventos, desde los cuales podemos sacar mucha información y una integración mucha más limpia, nos va a permitir crecer mucho alrededor de productos, y no tanto invertir en extenderlos.
Por otro lado, para los que ya usaramos Event Grid, se nos abre un escenario de gobierno muy interesante, pudiendo separar a publicadores y suscriptores, de tal forma que los recursos, los costes y el gobierno vaya por separado, permitiendo no "acoplarlos" unos a otros.
Sergio Hernández Mancebo
Azure MVP