How to Parse JSON Output from a Kentik Detect Alert

This how-to covers a simple approach to parsing the output from the Kentik alerting system so that you can shape it into into whatever form(s) you need for your particular use-case(s). In this case the JSON is parsed with PHP, but the general idea is of course equally applicable to other languages such as Python, Perl, Ruby, or Go.

This how-to is made up of the following topics:


Alerts and Alert Output

Kentik Detect’s alerting system is a powerful tool that informs users when network traffic meets a user-defined set of conditions. The alerting system supports several notification modes, including posting to customer-designated syslog and/or URL, which allows integration with external systems for functions such as ticketing and configuration management. The posted data, which provides information about the triggering conditions and the current status, is a set of JSON key:value pairs within an HTTP response body. This how-to is intended for any customer or partner that is interested in processing this JSON notification data. It focuses on using PHP to parse the JSON and to write the desired values to a human-readable file on a web server.

Kentik Detect customers use alerts to monitor various metrics in the data that is ingested into the Kentik Data Engine (KDE), including information on devices, interfaces, IP/CIDR, Geo, ASN, and ports. The alerting system is very flexible and can be set up to inform users about a variety of conditions, including DDoS attack, the crossing of bandwidth thresholds (indicating the need to allocate more bandwidth), or changes in the status of device interfaces. The conditions are specified as a query that is run at a polling interval. If the query returns matches a specified number of times within a specified duration then the alert goes into alarm state, runs up to two user-specified supplemental queries to gather additional information, and begins generating notifications.

The use-case example for this how-to is a DDoS attack. To follow the how-to you’ll need:

  • A basic understanding of Kentik Detect alerts (for a full explanation please see Alerts Overview in the Kentik Knowledge Base).
  • A web server available for testing that is reachable from the Kentik Detect public SaaS deployment.


Step by Step

The flow of steps involved in parsing the alert notification JSON with PHP is as follows:

  1. Create a JSON-parsing PHP script similar to the script on GitHub that is referenced in JSON-parsing PHP script below.
  2. Create a test directory on your web server for your PHP script, check ownership and permissions, and copy the script to this directory, e.g.:
    http://your_domain.com/test/json-test.php
  3. In the Kentik Detect portal, go to Admin » Tags and confirm that a MYNETWORK tag is listed. This tag is typically defined with your network ASN or IP subnets. If you don’t already have one, see Add a MYNETWORK Tag.
  4. In the Kentik Detect portal, go to Admin » Alerts » Global Alert Settings. In the Notification URL field, enter the full path to the location (from step 2) of your PHP script.
  5. Define a TCP Syn alert based on the queries provided in Defining an Alert below.
  6. On the web server where you put your PHP script, start a packet capture on port 80 so that you can see the pcap example of an HTTP POST with JSON:
    tcpdump -i eth0 port 80 -vvv -A -s0 -w /tmp/json-test.pcap
  7. In the Kentik Detect portal, go to the Alert Dashboard (click Alerts on the top navbar). When your alert enters alarm state it will be displayed as a row in the dashboard’s table, and an alert notification will be sent to the URL of the PHP script. At that point, stop the packet capture.
  8. To see the unparsed JSON in the notification from the alerting system (similar to JSON output below), you can read the JSON file:
    tcpdump -vvv -A -s0 -r /tmp/json-test.pcap
  9. In your web browser, open the file at the following URL to see the alert information extracted using PHP. The output should like like the example shown in Parsed output below:
    /tmp/testFile.txt


JSON-parsing PHP Script

This PHP script listens for HTTP POST messages, parses the JSON body and writes the results from the primary query and two supplemental queries to a file. This basic example can be extended to use the query results to activate ticketing/NOC notifications, mitigation policies, and more. The script file can be downloaded from the Kentik integrations directory on GitHub.


Defining an Alert

Needless to say, before we can test the PHP parsing script we have to have an alert that sends a notification to parse. The following queries are for an example alert that returns the following types of values from its primary and supplemental queries:

  • primary: destination IP, device name
  • supplemental 1: layer 4 destination port
  • supplemental 2: destination device interface

Example primary query:

select now(), i_device_name, ipv4_dst_addr as ipv4_dst_addr$_key_, round(sum(both_pkts)/%lookbackseconds%) as f_sum_both_pkts$_out_pps, round((sum(both_bytes)/%lookbackseconds%/1000000)*8) as f_sum_both_bytes$_out2_mbps from all_devices where protocol=6 and tcp_flags= 2 AND i_device_type != ‘host’ AND src_flow_tags NOT LIKE ‘%MYNETWORK%’ and ctimestamp > %lookbackseconds% group by i_device_name, ipv4_dst_addr having ((sum(both_pkts)/%lookbackseconds%) > 20000) or ((sum(both_bytes)/%lookbackseconds%/1000000)*8) > 20 order by f_sum_both_pkts$_out_pps DESC limit 100

Example supplemental query 1:

select i_device_name, l4_dst_port, sum(both_bytes) as f_sum_both_bytes from all_devices where ipv4_dst_addr=’%key%’ and protocol=6 and tcp_flags= 2 and ctimestamp > %lookbackseconds% group by i_device_name, l4_dst_port order by f_sum_both_bytes limit 10

Example supplemental query 2:

select i_device_name, input_port, sum(both_bytes) as f_sum_both_bytes from all_devices where ipv4_dst_addr=’%key%’ and protocol=6 and tcp_flags= 2 and ctimestamp > %lookbackseconds% group by i_device_name, input_port order by f_sum_both_bytes limit 10


JSON Output

An example of pre-parsed notification JSON is shown below. The JSON is constructed as an array containing a set of elements, some of which may be key:value pairs and others of which may themselves be arrays, including arrays for the main query result and the results of the two supplemental queries. In the example, line breaks have been inserted between these query arrays to make them easier to see.

Note: For each return value in the supplemental query an additional array will be created under supl_sql_one_value and supl_sql_two_value. For instance, if an attack targets a single destination IP address, but multiple destination ports, each destination port will be listed in a separate array, where Array ([ X ] becomes the next number. The example supl_sql_one_value includes one destination port (0). If the attack targeted 2 ports the next Array identifier would be 1 i.e. Array ([1] => etc. To process each Array, add logic to your PHP script to read each entry.

Array ( [message_type] => CHALERT [severity] => CRITICAL [type] => ALARM [alert_id] => 3483 [event_id] => 215027 [key_value] => 38.118.79.72 [key_name] => ipv4_dst_addr [out1_name] => pps [out1_value] => 137 [out2_name] => mbps [out2_value] => 2 [alert_start] => 1439312245 [alert_end] => 0 [notification_sent] => 1439312713 [alert_name] => JSON_test2 [alert_desc] =>
[query_result] => Array ( [f_sum_both_bytes$_out2_mbps] => 2 [f_sum_both_pkts$_out_pps] => 137 [i_device_name] => cat2_readnews [ipv4_dst_addr$_key_] => 38.118.79.72 [now] => 2015-08-11T17:04:53.804936Z ) [clear_comment] => [main_sql] => select now(), i_device_name, ipv4_dst_addr as ipv4_dst_addr$_key_, round(sum(both_pkts)/%lookbackseconds%) as f_sum_both_pkts$_out_pps, round((sum(both_bytes)/%lookbackseconds%/1000000)*8) as f_sum_both_bytes$_out2_mbps from all_devices where protocol=6 AND i_device_type != ‘host’ AND dst_flow_tags like ‘%MYNETWORK%’ and ctimestamp > %lookbackseconds% group by i_device_name, ipv4_dst_addr having ((sum(both_pkts)/%lookbackseconds%) > 30) or ((sum(both_bytes)/%lookbackseconds%/1000000)*8) > 50 order by f_sum_both_bytes$_out2_mbps DESC limit 2 [supl_sql_one] => select i_device_name, l4_dst_port, sum(both_bytes) as f_sum_both_bytes from all_devices where ipv4_dst_addr=’%key%’ and protocol=6 and ctimestamp > %lookbackseconds% group by i_device_name, l4_dst_port order by f_sum_both_bytes limit 10 [supl_sql_two] => select i_device_name, l4_dst_port, sum(both_bytes) as f_sum_both_bytes from all_devices where ipv4_dst_addr=’%key%’ and protocol=6 and ctimestamp > %lookbackseconds% group by i_device_name, l4_dst_port order by f_sum_both_bytes limit 10
[supl_sql_one_value] => Array ( [0] => Array ( [f_sum_both_bytes] => 5849088 [i_device_name] => cat2_readnews [l4_dst_port] => 0 ) )
[supl_sql_two_value] => Array ( [0] => Array ( [f_sum_both_bytes] => 5849088 [i_device_name] => cat2_readnews [input_port] => 30 ) ) [debug] => )


Parsed Output

The following example shows the parsed output you can expect to see in testFile.txt. Because supplemental queries are specified in the alert that’s generating the notification, the parsed output includes values from the arrays corresponding to the supplemental queries (see the pre-parsed output in JSON Output):

ALARM
CRITICAL
alert_id: 3483
event_id: 350074
key name: ipv4_dst_addr
key value: 204.186.16.136
device_name: gateway_nyc_xyz_net
l4_dst_port_sup1-1: 0
l4_dst_port_sup1-2:
device_input_int_sup2-1: 30
device_input_int_sup2-2:
source_IP_addresssup1-1: (not used for this test)
source_IP_addresssup1-2: (not used for this test)

So there you have it: a simple approach to using the output from the Kentik alerting system. By modifying and/or extending the PHP script you can shape the output into whatever form you need for your particular use-case. For further information on the possible use cases and how to implement, contact your Kentik Solutions Engineer.