Hooks

Hooks are pre-defined JavaScript functions in the scripting system that are being attached to a certain point in the network packet capture - dissect - query pipeline of Kubeshark.

Kubeshark provides OSI L4 and L7 hooks that enable running functions whenever a packet is captured or a new application-layer message is dissected.

Hooks function arguments with type object can be printed to console with the purpose of seeing the data structure of that argument, like;

console.log(JSON.stringify(data))

A couple of examples can be found at the end of this section.

Hook description includes an Arguments section that explains the hook’s arguments’ Go data structure. These Go data structures provide hints about the typings that emerge in the JavaScript runtime. Please refer to the JSON and Go page to understand how JSON encoding works in Go language if you’re not familiar with the Go language.

onPacketCaptured(info: object)

function onPacketCaptured(info) {
  // Your code goes here
}

The onPacketCaptured is an OSI L4 network hook. It is called whenever a new network packet is captured by Kubeshark.

On a busy cluster, the call frequency of this hook can go more than a 10000 times per second. Because of that; a poorly optimized onPacketCaptured implementation can have a performance impact on the network traffic capture speed of Kubeshark. Therefore it’s logical to not call certain helpers (e.g. console.log or vendor.slack) and instead use this hook to aggregate data into a global variable and then handle the aggregated data in another hook or a job:

var packetCount = 0;
var totalKB = 0;

function onPacketCaptured(info) {
  // Example of data aggregation, packet and KB counter
  packetCount++;
  totalKB += info.length / 1000;
}

function yourJob() {
  // Handle `packetCount` and `totalKB` here
}

// Schedule a call to function `yourJob` every minute
jobs.schedule("example-job", "0 */1 * * * *", yourJob);

The call to hook onPacketCaptured does not depend on user’s action, it’s sourced from network traffic capture.

Arguments

Arguments of onPacketCaptured hook:

info

type Info struct {
	Timestamp     time.Time `json:"timestamp"`
	CaptureLength int       `json:"captureLength"`
	Length        int       `json:"length"`
	Truncated     bool      `json:"truncated"`
	Fragmented    bool      `json:"fragmented"`
}

timestamp is the UTC timestamp of the moment that packet is captured.

captureLength is the length of the capture.

length is the actual length of packet.

truncated whether the packet is truncated or not. See packet truncation for more info.

onItemCaptured(data: object)

function onItemCaptured(data) {
  // Your code goes here
}

The hook onItemCaptured is an OSI L7 network hook that is called whenever a TCP/UDP stream is captured, reassembled and successfully dissected by one of the protocol parsers of Kubeshark.

This hook is triggered less compared to the onPacketCaptured hook, since multiple packets translate into a protocol-level message (e.g. an HTTP request-response pair, a Kafka publish, a Kafka consume or an AMQP exchange declare).

The item’s scope is determined by the corresponding application layer protocol as one can imagine. For example; an HTTP request-response pair contains a lot parameters while an AMQP exchange declare is quite a simple message.

The call to hook onItemCaptured does not depend on user’s action, it’s sourced from network traffic capture.

Arguments

Arguments of onItemCaptured hook:

data

See the updated data structure: https://github.com/kubeshark/api/blob/master/api.go#L273

onItemQueried(data: object)

The hook onItemQueried is called whenever an already captured and stored TCP/UDP stream is queried or fetched through the dashboard. All of its other aspects are same with the onItemCaptured hook.

The call to hook onItemQueried depends on user’s action, it’s not sourced from network traffic capture.

Arguments

Same as onItemCaptured hook.

onJobPassed(tag: string, cron: string, limit: number)

function onJobPassed(tag, cron, limit) {
  // Your code goes here
}

The hook onJobPassed is called whenever a job passes.

Arguments

tag is job tag.

cron is the cron statement.

limit is the limit of job runs.

onJobFailed(tag: string, cron: string, limit: number)

function onJobFailed(tag, cron, limit, err) {
  // Your code goes here
}

The hook onJobFailed is called whenever a job fails.

Arguments

tag is job tag.

cron is the cron statement.

limit is the limit of job runs.

err is the error message.

Example values of the data argument

Here are some example values of the data argument that being used in onItemCaptured and onItemQueried hooks:

HTTP

{
  "dst": {
    "ip": "10.0.0.99",
    "name": "",
    "port": "8086"
  },
  "elapsedTime": 23,
  "failed": false,
  "id": "192.168.49.2:8897/000000025258.pcap-0",
  "index": 0,
  "namespace": "default",
  "node": {
    "ip": "192.168.49.2",
    "name": "my-cluster"
  },
  "outgoing": false,
  "passed": false,
  "protocol": {
    "abbr": "HTTP",
    "backgroundColor": "#326de6",
    "fontSize": 12,
    "foregroundColor": "#ffffff",
    "layer4": "tcp",
    "longName": "Hypertext Transfer Protocol -- HTTP/1.1",
    "macro": "http",
    "name": "http",
    "ports": [
      "80",
      "443",
      "8080"
    ],
    "priority": 0,
    "referenceLink": "https://datatracker.ietf.org/doc/html/rfc2616",
    "version": "1.1"
  },
  "request": {
    "bodySize": 124,
    "cookies": {},
    "headers": {
      "Accept-Encoding": "gzip",
      "Authorization": "Token edO4nlXbD5cfx8nw9_94LMO4tvGJ_xeMQMiFc6J_DNYFAGRe0YIgG8gz98UwDKOa6otCzml3SNw_c5TiDuB4eA==",
      "Content-Length": "124",
      "Host": "10.0.0.99:8086",
      "User-Agent": "influxdb-client-go/2.12.2 (linux; amd64)"
    },
    "headersSize": -1,
    "httpVersion": "HTTP/1.1",
    "method": "POST",
    "path": "/api/v2/write",
    "pathSegments": [
      "api",
      "v2",
      "write"
    ],
    "postData": {
      "mimeType": "",
      "params": [],
      "text": "PerformanceKPIs,namespace=sock-shop,path=/basket.html,service=front-end.sock-shop latency=51,status=200 1678675066165748213\n"
    },
    "queryString": {
      "bucket": "Metrics",
      "org": "Kubeshark",
      "precision": "ns"
    },
    "targetUri": "/api/v2/write?bucket=Metrics&org=Kubeshark&precision=ns",
    "url": "/api/v2/write?bucket=Metrics&org=Kubeshark&precision=ns"
  },
  "requestSize": 428,
  "response": {
    "bodySize": 0,
    "content": {
      "encoding": "base64",
      "mimeType": "",
      "size": 0
    },
    "cookies": {},
    "headers": {
      "Date": "Mon, 13 Mar 2023 02:37:46 GMT",
      "X-Influxdb-Build": "OSS",
      "X-Influxdb-Version": "2.6.1"
    },
    "headersSize": -1,
    "httpVersion": "HTTP/1.1",
    "redirectURL": "",
    "status": 204,
    "statusText": "No Content"
  },
  "responseSize": 114,
  "src": {
    "ip": "192.168.49.2",
    "name": "kubernetes.default",
    "port": "36848"
  },
  "startTime": "2023-03-13T02:37:46.172360504Z",
  "stream": "000000025258.pcap",
  "timestamp": 1678675066172,
  "tls": false,
  "worker": "192.168.49.2:30001"
}

DNS

{
  "dst": {
    "ip": "172.17.0.3",
    "name": "kube-dns.kube-system",
    "port": "53"
  },
  "elapsedTime": 0,
  "failed": false,
  "id": "192.168.49.2:8897/000000025277_udp.pcap-0",
  "index": 0,
  "namespace": "kube-system",
  "node": {
    "ip": "192.168.49.2",
    "name": "my-cluster"
  },
  "outgoing": false,
  "passed": false,
  "protocol": {
    "abbr": "DNS",
    "backgroundColor": "#606060",
    "fontSize": 12,
    "foregroundColor": "#ffffff",
    "layer4": "udp",
    "longName": "Domain Name System",
    "macro": "dns",
    "name": "dns",
    "ports": [],
    "priority": 4,
    "referenceLink": "https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml",
    "version": "0"
  },
  "request": {
    "opCode": "Query",
    "questions": [
      {
        "class": "IN",
        "name": "session-db.sock-shop.svc.cluster.local",
        "type": "A"
      }
    ]
  },
  "requestSize": 154,
  "response": {
    "answers": [
      {
        "class": "IN",
        "cname": "",
        "ip": "10.101.46.75",
        "mx": "",
        "name": "session-db.sock-shop.svc.cluster.local",
        "ns": "",
        "opt": "",
        "ptr": "",
        "soa": "",
        "srv": "",
        "ttl": 24,
        "txts": "",
        "type": "A",
        "uri": ""
      }
    ],
    "code": "No Error"
  },
  "responseSize": 154,
  "src": {
    "ip": "172.17.0.1",
    "name": "",
    "port": "33305"
  },
  "startTime": "2023-03-13T02:37:49.958762876Z",
  "stream": "000000025277_udp.pcap",
  "timestamp": 1678675069958,
  "tls": false,
  "worker": "192.168.49.2:30001"
}