
Una libreria Go per utilizzare l'API websocket di zeek broker.
Questa libreria implementa l'interfaccia websocket di Zeek Broker.
Vengono fornite funzioni helper con corrispondenze ragionevoli tra i tipi Zeek e Go.
La libreria contiene due pacchetti:
encodingencoding modella la struttura dati ricorsiva basata su JSON per rappresentare i tipi Zeek (la struct Data), oltre alla codifica Broker degli eventi Zeek e dei messaggi di errore (la struct DataMessage). Queste strutture possono (e in alcuni casi devono) essere usate direttamente (vedi l'esempio di subscription nella prossima sezione), ma alcune funzioni helper rendono più comoda la costruzione dei messaggi. Per costruire manualmente una string Zeek:
zeekString := encoding.Data{
DataType: encoding.TypeString,
DataValue: "foo",
}
...oppure tramite la funzione helper:
zeekString := encoding.String("foo")
La funzione helper vector, in particolare, è una funzione variadica che accetta encoding.Data:
zeekVector := encoding.Vector(encoding.Count(1), encoding.Count(2), encoding.Count(3))
Infine, gli eventi possono essere creati direttamente:
zeekEvent := encoding.NewEvent("some_event_name", zeekVector, zeekString)
clientclient fornisce la colla websocket per comunicare con l'API WS del broker, incapsulando github.com/gorilla/websocket:
Per pubblicare un evento:
broker, err := client.NewClient(...)
err := broker.PublishEvent("/the/topic", zeekEvent)
Le sottoscrizioni ai topic vengono passate come slice di stringhe a client.Newclient(). Il metodo ReadEvent() del client restituisce un singolo evento da Broker (su uno qualsiasi dei topic sottoscritti), oppure un errore che può verificarsi nella libreria stessa o errori ricevuti da Broker):
broker, err := client.NewClient(..., []string{"/the/topic"})
topic, zeekEvent, err := broker.ReadEvent()
Se la connessione al broker viene chiusa normalmente, la funzione client.IsNormalWebsocketClose() può essere usata per controllare l'errore restituito.
Il codice client deve accedere ai valori degli argomenti dell'evento tramite type assertion:
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 gestione e l'invio asincrono degli eventi ricevuti tramite sottoscrizioni è meglio implementarli come un wrapper di Client.ReadEvent(). Una semplice implementazione è fornita in client.AsyncSubscription().
La gestione più avanzata della connessione websocket (ad esempio, impostazione dei timeout, gestione della riconnessione, ecc.) è meglio implementarla come wrapper di client.Client, oppure come implementazione nuova/sostitutiva che usi il pacchetto encoding (contributi/PR sono benvenuti!).
Le connessioni di rete di Broker (sia native, sia tramite interfaccia websocket) abilitano TLS per impostazione predefinita con una configurazione particolare che disabilita la verifica dell'host e seleziona un insieme di cipher che consentono la crittografia senza certificati (Diffie-Hellman anonimo / AECDH). Per usare questa modalità è necessario passare weirdtls.BrokerDefaultTLSDialer come argomento della funzione dialer a encoding.NewClient. Nota che questo introduce OpenSSL come dipendenza.
In alternativa, può essere usata l'implementazione crypto/tls della libreria standard se entrambe le parti (il client e zeek/broker) sono configurate per usare TLS con certificati. Questa libreria fornisce una pratica funzione helper (securetls.MakeSecureDialer()) che restituisce una funzione dialer a partire dai file PEM per la CA e per certificato/chiave del client. Vedi questo caso btest per un esempio di questa configurazione.
Infine, TLS può essere disattivato per le connessioni broker usando redef Broker::disable_ssl = T;. Vedi questo caso btest per un esempio in cui encoding.NewClient viene chiamato con argomenti per un funzionamento non sicuro.
In zeek 7.2 l'API websocket verrà spostata da broker al framework Cluster e l'impostazione predefinita sarà disattivare TLS. Questo caso btest usa le nuove funzioni lato zeek e dimostra l'utilizzo di questa libreria chiamando encoding.NewClient() con l'argomento secure impostato su false.
Quando zeek 7.2 diventerà la release LTS, una nuova versione (major) di questa libreria abbandonerà il supporto per la modalità TLS AECDH descritta nella sezione precedente, eliminando la dipendenza da OpenSSL.
Eseguendo uno script broker lato zeek:
$ cd example/
$ zeek listen.zeek
Ora esegui l'esempio:
$ 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)
...nel frattempo lo 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 maggior parte degli helper e delle strutture dati di base nel pacchetto encoding dispone di unit test (esegui go test ./...).
I test end-to-end sono implementati come due casi btest (esegui cd tests/; btest).