
Une bibliothèque Go pour utiliser l'API websocket de zeek broker.
Cette bibliothèque implémente l'interface websocket de Zeek Broker.
Des fonctions d'assistance sont fournies avec des correspondances raisonnables entre les types Zeek et Go.
La bibliothèque contient deux paquets :
encodingencoding modélise la structure de données récursive basée sur JSON pour représenter les types Zeek (la structure Data), ainsi que
l'encodage Broker des événements Zeek et des messages d'erreur (la structure DataMessage). Ces structures peuvent (et dans certains cas doivent)
être utilisées directement (voir l'exemple d'abonnement dans la section suivante), mais certaines fonctions d'assistance rendent la construction de messages
plus pratique. Pour construire manuellement une string Zeek :
zeekString := encoding.Data{
DataType: encoding.TypeString,
DataValue: "foo",
}
...ou via la fonction d'assistance :
zeekString := encoding.String("foo")
La fonction d'assistance vector, en particulier, est une fonction variadique qui accepte des encoding.Data :
zeekVector := encoding.Vector(encoding.Count(1), encoding.Count(2), encoding.Count(3))
Enfin, les événements peuvent être créés directement :
zeekEvent := encoding.NewEvent("some_event_name", zeekVector, zeekString)
clientclient fournit la partie websocket pour communiquer avec l'API WS du broker, en enveloppant github.com/gorilla/websocket :
Pour publier un événement :
broker, err := client.NewClient(...)
err := broker.PublishEvent("/the/topic", zeekEvent)
Les abonnements aux topics sont passés sous forme d'une tranche de chaînes à client.Newclient(). La méthode ReadEvent() du client retourne un seul événement du Broker (sur l'un des topics abonnés), ou une erreur qui pourrait se produire dans la bibliothèque elle-même ou des erreurs reçues du Broker) :
broker, err := client.NewClient(..., []string{"/the/topic"})
topic, zeekEvent, err := broker.ReadEvent()
Si la connexion au broker est fermée proprement, la fonction client.IsNormalWebsocketClose() peut être utilisée pour vérifier l'erreur retournée.
Le code client doit accéder aux valeurs des arguments d'événement via des assertions de type :
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
La gestion et la répartition asynchrones des événements reçus via les abonnements seraient mieux implémentées comme un wrapper de Client.ReadEvent(). Une implémentation simple est fournie dans client.AsyncSubscription().
Une gestion plus avancée de la connexion websocket (par exemple, définition de délais d'attente, gestion de la reconnexion, etc.) est mieux implémentée comme un wrapper de client.Client, ou une implémentation nouvelle/alternative qui utilise le paquet encoding (les contributions/PRs sont les bienvenues !).
Les connexions réseau Broker (à la fois natives et via l'interface websocket) activent TLS par défaut avec une configuration inhabituelle qui désactive la vérification de l'hôte et sélectionne un ensemble de chiffrements permettant le chiffrement sans certificats (Diffie-Hellman anonyme / AECDH). Pour utiliser ce mode, il faut passer weirdtls.BrokerDefaultTLSDialer comme argument de fonction dialer à encoding.NewClient. Notez que cela ajoute OpenSSL comme dépendance.
Alternativement, l'implémentation de la bibliothèque standard crypto/tls peut être utilisée si les deux côtés (le client et zeek/broker) sont configurés pour utiliser TLS avec des certificats. Cette bibliothèque fournit une fonction d'assistance pratique (securetls.MakeSecureDialer()) qui retourne une fonction dialer à partir des fichiers PEM pour l'AC et le certificat/clé client. Voir ce cas btest pour un exemple de cette configuration.
Enfin, TLS peut être désactivé pour les connexions broker en utilisant redef Broker::disable_ssl = T;. Voir ce cas btest pour un exemple où encoding.NewClient est appelé avec des arguments pour un fonctionnement non sécurisé.
Dans zeek 7.2, l'API websocket sera déplacée de broker vers le framework Cluster, et le défaut est de désactiver TLS. Ce cas btest utilise les nouvelles fonctions côté zeek et montre comment utiliser cette bibliothèque en appelant encoding.NewClient() avec l'argument secure défini sur false.
Lorsque zeek 7.2 deviendra la version LTS, une nouvelle version (majeure) de cette bibliothèque abandonnera le support du mode TLS AECDH décrit dans la section ci-dessus, supprimant la dépendance OpenSSL.
Exécution d'un script broker côté zeek :
$ cd example/
$ zeek listen.zeek
Exécutez maintenant l'exemple :
$ 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)
...pendant ce temps, le script 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 plupart des fonctions d'assistance et des structures de données de base du paquet encoding ont des tests unitaires (exécutez go test ./...).
Les tests de bout en bout sont implémentés comme deux cas btest (exécutez cd tests/; btest).