
zeek broker의 websocket API를 사용하기 위한 Go 라이브러리
이 라이브러리는 Zeek Broker websocket 인터페이스를 구현합니다.
Zeek 타입과 Go 타입 간의 합리적인 매핑을 제공하는 헬퍼 함수가 포함되어 있습니다.
이 라이브러리는 두 개의 패키지를 포함합니다:
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는 github.com/gorilla/websocket을 래핑하여 broker WS API와 통신할 수 있는 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)를 선택하는 특이한 구성을 사용합니다. 이 모드를 사용하려면 weirdtls.BrokerDefaultTLSDialer를 encoding.NewClient의 다이얼러 함수 인수로 전달해야 합니다. 참고로 이로 인해 OpenSSL이 의존성으로 포함됩니다.
또는 클라이언트와 zeek/broker 양쪽 모두 인증서를 사용하는 TLS를 사용하도록 구성된 경우 표준 라이브러리 crypto/tls 구현을 사용할 수 있습니다. 이 라이브러리는 CA 및 클라이언트 인증서/키의 PEM 파일이 주어지면 다이얼러 함수를 반환하는 편리한 헬퍼 함수(securetls.MakeSecureDialer())를 제공합니다. 이 구성의 예는 이 btest 케이스를 참조하세요.
마지막으로 redef Broker::disable_ssl = T;를 사용하여 broker 연결에 대해 TLS를 끌 수 있습니다. encoding.NewClient가 비보안(Insecure) 작업을 위한 인수와 함께 호출되는 예는 이 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 ./... 실행).
엔드투엔드 테스트는 두 개의 btest 케이스로 구현됩니다(cd tests/; btest 실행).