2017-12-12 1 views
0

Ich habe einen Protobuf, den ich durch Logstash füttern will. Einige der Werte sehen binär formatiert:Convert gepackte Zeichenfolge von Protobuf nach formatiert über Logstash

Beim Drucken über den rubydebug Codec

Ich erhalte Werte wie:

rData => '\xD8:\xC9$' 

Dies, weil durch protobuf Vorlage zu sein scheint hat:

optional :bytes, :rData, 5 

Welche ... tut was es auf der Dose - übergibt die rohen Bytes durch Logstash, die dann annimmt, dass sie Text sind.

Also, dass rData Zeile würde als 216.58.201.36 dekodieren, die die Antwort für www.google.com ist.

Wie kann ich dies in elasticsearch in ein nützliches Format konvertieren?

Antwort

0

Um dies zu erreichen, müssen Sie ein bisschen Rubin selbst schreiben.

Aber keine Sorge, es ist einfacher als es sich anhört, Sie können einfach in die Logstash-Konfigurationsdatei rubinieren.

Erstens:

  • Stellen Sie Ihren Ausgangs Codec rubydebug so dass es die Datenstruktur druckt - Sie werden diese identifizieren müssen, welche Felder Sie wollen.

Also für mein Beispiel (der Kürze halber snipped):

Wir sind im rData Bereich interessiert.

"socketProtocol" => 1, 
    "@timestamp" => 2017-12-12T10:26:41.910Z, 
    "requestorId" => "", 
      "port" => 47788, 
     "response" => { 
      "rcode" => 0, 
       "rrs" => [ 
     [0] { 
      "rType" => 1, 
      "rData" => "\xD8:\xC9$", 
      "rClass" => 1, 
      "rName" => "www.google.com.", 
       "rTtl" => 300 
     } 
    ], 

Wir haben auch einige Beispiele von mehr rData Felder, wobei der Wert in rubydebug ist:

"rData" => "*\x00\[email protected]\t\b\v\x00\x00\x00\x00\x00\x00 \x04", 

die in Elasticsearch Rendering endet als:

"rData": "*\u0000\[email protected]\t\b\u000b\u0000\u0000\u0000\u0000\u0000\u0000 \u0004", 

So extrahieren wir dies mit event.get("response"), so können wir die Existenz testen (notwendig, weil in meinem Fall response Felder mit keinen Daten sein werden):

filter { 
    if [response] { 
    ruby { 
     code => 

     # response rData can be a different things. 
     #usually an ipV4 address, or an ipv6. 
     #But they're usually written in different formats - ipv4 is dotted quads, 
     #where ipv6 is hex and double-bytes 
     #so we look at the (unpacked) string length, and see if there are 4 (or more) 'uint64s' in there. 
     #and substitute accordingly. 
     ' 
     response = event.get("response") 
     if (response and response["rrs"] and response["rrs"][0] and response["rrs"][0]["rData"]) 
      rdata = response["rrs"][0]["rData"] 
      hex_value = rdata.unpack("H*").join("") 
      ip_value = rdata.unpack("C4").join(".") 
      length_rdata = rdata.unpack("L*").length 
      if (length_rdata >= 4) 
      event.set("[response][decoded_rdata]", hex_value) 
      else 
      event.set("[response][decoded_rdata]", ip_value) 
      end 
     end 
     ' 
    } 
    } 
} 

Hinweis - diese prüft die Länge des rData Wert, und wenn es „lang“ ist dann nimmt sie eine IPv6-Adresse und Formate als Hex ist, und wenn es kurz ist, geht davon aus, dass es IPv4- und Formate wie die herkömmliche ist ' gepunktetes Quad.

Es fügt dann zu einem neuen Unterfeld response.decoded_rdata hinzu, das wahrscheinlich für elasticsearch nützlicher ist als tieferes Verschachteln.

Wir haben auch einen zusätzlichen Schnipsel haben die ‚byte‘ Codierung des from/to/messageId Feldes zu handhaben, die weitgehend ähnlich ist:

ruby { 
    code => 
     #take to and from fields, and assume they're packed IP addresses. 
     #take messageId and convert to hex. 
     'event.set("from", event.get("from").unpack("C4").join(".")); 
     event.set("to", event.get("to").unpack("C4").join(".")); 
     event.set("messageId", event.get("messageId").unpack("H*").join("")); 
     ' 
    } 
Verwandte Themen