
zeek brokerのwebsocket APIを使用するためのGoライブラリ
このライブラリは、Zeek Broker WebSocketインターフェースを実装しています。
ZeekとGoの型の間の合理的なマッピングを備えたヘルパー関数が提供されています。
このライブラリには2つのパッケージが含まれています:
encodingencodingは、Zeekの型を表す再帰的なJSONベースのデータ構造(Data構造体)と、
ZeekのイベントおよびエラーメッセージのBrokerエンコーディング(DataMessage構造体)をモデル化しています。これらの構造体は、(場合によっては必須として)
直接使用できます(次のセクションのサブスクリプション例を参照)。ただし、いくつかのヘルパー関数を使用すると、メッセージの構築が
より便利になります。Zeekのstringを手動で構築するには:
zeekString := encoding.Data{
DataType: encoding.TypeString,
DataValue: "foo",
}
...またはヘルパーを使う場合:
zeekString := encoding.String("foo")
特にvectorヘルパーは、encoding.Dataを受け取る可変長引数関数です:
zeekVector := encoding.Vector(encoding.Count(1), encoding.Count(2), encoding.Count(3))
最後に、イベントは直接作成できます:
zeekEvent := encoding.NewEvent("some_event_name", zeekVector, zeekString)
clientclientは、Broker WS APIと通信するためのWebSocket接続を提供し、github.com/gorilla/websocketをラップしています:
イベントを公開するには:
broker, err := client.NewClient(...)
err := broker.PublishEvent("/the/topic", zeekEvent)
トピックのサブスクリプションは、文字列のスライスとしてclient.Newclient()に渡されます。クライアントのReadEvent()メソッドは
Brokerから単一のイベントを(サブスクライブした任意のトピックで)返すか、ライブラリ自体で発生する可能性のあるエラー、
またはBrokerから受信したエラーを返します:
broker, err := client.NewClient(..., []string{"/the/topic"})
topic, zeekEvent, err := broker.ReadEvent()
Broker接続が正常に閉じられた場合、client.IsNormalWebsocketClose()関数を使用して
返されたエラーを確認できます。
クライアントコードは、型アサーションを介してイベント引数の値にアクセスする必要があります:
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
サブスクリプションを介して受信したイベントの非同期処理とディスパッチは、Client.ReadEvent()のラッパーとして実装するのが最適です。
簡単な実装がclient.AsyncSubscription()に用意されています。
WebSocket接続のより高度な処理(タイムアウトの設定、再接続の処理など)は、client.Clientのラッパー、またはencodingパッケージを
使用する新しい/置き換え実装として実装するのが最適です(貢献/PRは歓迎します!)。
Brokerネットワーク接続(ネイティブおよびWebSocketインターフェースの両方)は、デフォルトでTLSを有効にしますが、ホスト検証を無効にし、
証明書なしの暗号化を可能にする暗号スイートのセットを選択するという奇妙な構成になっています(Anonymous Diffie-Hellman
/ AECDH)。このモードを使用するには、encoding.NewClientのダイヤラー関数引数としてweirdtls.BrokerDefaultTLSDialerを渡す必要があります。
これにより、依存関係としてOpenSSLが取り込まれることに注意してください。
あるいは、クライアントとzeek/brokerの両方(クライアントとzeek/broker)が証明書を使用したTLSを使用するように構成されている場合は、
標準ライブラリのcrypto/tls実装を使用できます。このライブラリは、CAとクライアント証明書/キーのPEMファイルが与えられると
ダイヤラー関数を返す便利なヘルパー関数(securetls.MakeSecureDialer())を提供します。
この構成の例については、このbtestケースを参照してください。
最後に、redef Broker::disable_ssl = T;を使用して、Broker接続のTLSをオフにできます。
安全でない操作の引数でencoding.NewClientが呼び出される例については、このbtestケースを参照してください。
zeek 7.2では、WebSocket APIはbrokerからClusterフレームワークに移され、デフォルトでTLSがオフになります。
このbtestケースは、新しいzeek側の関数を使用し、secure引数をfalseに設定してencoding.NewClient()を呼び出すことで
このライブラリを使用する方法を示しています。
zeek 7.2がLTSリリースになると、このライブラリの新しい(メジャー)バージョンは、上記のセクションで説明したAECDH TLSモードのサポートを廃止し、 OpenSSL依存関係を削除します。
zeek側のbrokerスクリプトを実行します:
$ cd example/
$ zeek listen.zeek
次に例を実行します:
$ 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)
...その間、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
encodingパッケージのほとんどのヘルパーと基本データ構造にはユニットテストがあります(go test ./...を実行)。
エンドツーエンドテストは、2つのbtestケースとして実装されています(cd tests/; btestを実行)。