
Una biblioteca Go para usar la API WebSocket de Zeek Broker.
Esta biblioteca implementa la interfaz websocket de Zeek Broker.
Se proporcionan funciones auxiliares con asignaciones razonables entre los tipos de Zeek y Go.
La biblioteca contiene dos paquetes:
encodingencoding modela la estructura de datos recursiva basada en JSON para representar tipos de Zeek (la estructura Data), así como
la codificación Broker de eventos y mensajes de error de Zeek (la estructura DataMessage). Estas estructuras pueden (y en algunos casos deben)
usarse directamente (ver el ejemplo de suscripción en la siguiente sección), pero algunas funciones auxiliares facilitan la construcción de mensajes.
Para construir un string de Zeek manualmente:
zeekString := encoding.Data{
DataType: encoding.TypeString,
DataValue: "foo",
}
...o mediante la función auxiliar:
zeekString := encoding.String("foo")
La función auxiliar vector es en particular una función variádica que acepta encoding.Data:
zeekVector := encoding.Vector(encoding.Count(1), encoding.Count(2), encoding.Count(3))
Finalmente, los eventos se pueden crear directamente:
zeekEvent := encoding.NewEvent("some_event_name", zeekVector, zeekString)
clientclient proporciona el pegamento websocket para comunicarse con la API WS del broker, envolviendo github.com/gorilla/websocket:
Para publicar un evento:
broker, err := client.NewClient(...)
err := broker.PublishEvent("/the/topic", zeekEvent)
Las suscripciones a temas se pasan como un slice de strings a client.Newclient(). El método ReadEvent() del cliente
devuelve un único evento de Broker (en cualquiera de los temas suscritos), o un error que podría ocurrir en la propia biblioteca
o errores recibidos de Broker):
broker, err := client.NewClient(..., []string{"/the/topic"})
topic, zeekEvent, err := broker.ReadEvent()
Si la conexión con el broker se cierra correctamente, se puede usar la función client.IsNormalWebsocketClose() para comprobar
el error devuelto.
El código del cliente debe acceder a los valores de los argumentos del evento mediante aserciones de tipo:
if len(evt.Arguments) < someConstantGreaterOrEqualToOne {
// handle too few arguments case
}
if evt.Arguments[0].DataType != encoding.TypeString {
// handle unexpected data type case
}
stringArgument0, ok := evt.Arguments[0].DataValue.(string)
if !ok {
// handle type assertion error - this would indicate a bug (we trust+verify).
}
// now we use stringArgument0
El manejo asíncrono y el despacho de eventos recibidos mediante suscripciones se implementarían mejor como
un envoltorio de Client.ReadEvent(). En client.AsyncSubscription() se proporciona una implementación sencilla.
El manejo más avanzado de la conexión websocket (por ejemplo, establecer timeouts, gestionar la reconexión, etc.) se implementa mejor
como un envoltorio de client.Client, o una implementación nueva/sustituta que use el paquete encoding (¡las contribuciones/PRs son bienvenidas!).
Las conexiones de red de Broker (tanto las nativas como la interfaz websocket) habilitan TLS por defecto con una configuración peculiar
que desactiva la verificación del host y selecciona un conjunto de cifrados que permiten el cifrado sin certificados (Diffie-Hellman anónimo
/ AECDH). Para usar este modo, hay que pasar weirdtls.BrokerDefaultTLSDialer como argumento de función dialer a encoding.NewClient.
Ten en cuenta que esto añade OpenSSL como dependencia.
Alternativamente, se puede usar la implementación crypto/tls de la biblioteca estándar si ambos lados (el cliente y zeek/broker)
están configurados para usar TLS con certificados. Esta biblioteca proporciona una práctica función auxiliar
(securetls.MakeSecureDialer()) que devuelve una función dialer dados los archivos PEM de la CA y el certificado/clave del cliente.
Consulta este caso btest para ver un ejemplo de esta configuración.
Finalmente, se puede desactivar TLS para las conexiones de broker usando redef Broker::disable_ssl = T;.
Consulta este caso btest para ver un ejemplo donde se llama a encoding.NewClient
con argumentos para operación insegura.
En zeek 7.2, la API websocket se moverá de broker al framework Cluster, y el valor por defecto será desactivar
TLS. Este caso btest usa las nuevas funciones del lado de zeek y demuestra el uso de
esta biblioteca llamando a encoding.NewClient() con el argumento secure establecido en false.
Cuando zeek 7.2 se convierta en la versión LTS, una nueva versión (major) de esta biblioteca eliminará el soporte para el modo TLS AECDH descrito en la sección anterior, quitando la dependencia de OpenSSL.
Ejecutando un script de broker del lado de zeek:
$ cd example/
$ zeek listen.zeek
Ahora ejecuta el ejemplo:
$ cd example/
$ go build && ./example
2023/05/05 12:56:55 connected to remote endpoint with UUID=c9b0bfd6-3b8d-5de2-a51c-9af7b81aaad3 version=2.5.0-dev
2023/05/05 12:56:55 > topic=/topic/test | event ping("my-message": string, "1": count)
2023/05/05 12:56:55 < topic=/topic/test | event pong("my-message": string, "2": count)
2023/05/05 12:56:56 > topic=/topic/test | event ping("my-message": string, "2": count)
2023/05/05 12:56:56 < topic=/topic/test | event pong("my-message": string, "3": count)
...mientras tanto, el script de zeek:
peer added, [id=e537f8b4-de32-52ea-9587-4e6e15bdfe20, network=[address=127.0.0.1, bound_port=50690/tcp]]
receiver got ping: my-message, 1
receiver got ping: my-message, 2
La mayoría de las funciones auxiliares y estructuras de datos básicas del paquete encoding tienen pruebas unitarias (ejecuta go test ./...).
Las pruebas de extremo a extremo se implementan como dos casos de btest (ejecuta cd tests/; btest).