Skip to content

Commit 13831bb

Browse files
authored
Merge pull request #47 from cisagov/feature/add-snmp-data
feature: add snmp data
2 parents bc7013c + 6ee4e4b commit 13831bb

File tree

6 files changed

+124
-46
lines changed

6 files changed

+124
-46
lines changed

Makefile

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
.PHONY: run
1+
.PHONY: generate launch
2+
23
include .env
34
export
45

@@ -10,17 +11,15 @@ help:
1011
install-develop:
1112
pip install -e .
1213

13-
# target: install - Install application
14+
# target: install - Install production application
1415
install:
1516
pip install navv
1617

17-
# target: generate - Generate analysis from pcap
18+
# target: generate - Generate analysis excel sheet
19+
# optionally set PCAP_PATH to a relative pcap file path
20+
# example: make generate PCAP_PATH=test-path/to/file.pcap
1821
generate:
19-
navv generate -o analysis -p test-data/test_data.pcap -z test-data/logs test-customer
20-
21-
# target: load-metadata - Load metadata
22-
load-metadata:
23-
navv generate -o analysis -z test-data/logs test-customer
22+
navv generate -o analysis -z test-data/logs test-customer $(if $(PCAP_PATH), -p $(PCAP_PATH))
2423

2524
# target: launch - Launch GUI application
2625
launch:

src/navv/_version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
"""This file defines the version of this module."""
2-
__version__ = "3.0.5"
2+
__version__ = "3.1.0"

src/navv/bll.py

Lines changed: 17 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2,34 +2,13 @@
22
import os
33
import pandas as pd
44

5-
from navv.zeek import perform_zeekcut
65
from navv.utilities import get_mac_vendor, timeit
76
from navv.validators import is_ipv4_address, is_ipv6_address
87

98

109
MAC_VENDORS_JSON_FILE = os.path.abspath(__file__ + "/../" + "data/mac-vendors.json")
1110

1211

13-
def get_zeek_data(zeek_logs):
14-
"""Return a list of Zeek conn.log data."""
15-
return (
16-
perform_zeekcut(
17-
fields=[
18-
"id.orig_h",
19-
"id.resp_h",
20-
"id.resp_p",
21-
"proto",
22-
"conn_state",
23-
"orig_l2_addr",
24-
"resp_l2_addr",
25-
],
26-
log_file=os.path.join(zeek_logs, "conn.log"),
27-
)
28-
.decode("utf-8")
29-
.split("\n")[:-1]
30-
)
31-
32-
3312
def get_zeek_df(zeek_data: list, dns_data: dict):
3413
"""Return a pandas dataframe of the conn.log data with its dns data."""
3514
zeek_data = [row.split("\t") for row in zeek_data]
@@ -163,3 +142,20 @@ def get_inventory_report_df(zeek_df: pd.DataFrame):
163142
)
164143

165144
return grouped_df
145+
146+
147+
@timeit
148+
def get_snmp_df(zeek_data: list):
149+
"""Return a pandas dataframe of the snmp.log data."""
150+
zeek_data = [row.split("\t") for row in zeek_data]
151+
return pd.DataFrame(
152+
zeek_data,
153+
columns=[
154+
"src_ip",
155+
"src_port",
156+
"dst_ip",
157+
"dst_port",
158+
"version",
159+
"community",
160+
],
161+
)

src/navv/commands.py

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
# Third-Party Libraries
77
import click
8-
from navv.bll import get_inventory_report_df, get_zeek_data, get_zeek_df
8+
from navv.bll import get_inventory_report_df, get_snmp_df, get_zeek_df
99

1010
# cisagov Libraries
1111
from navv.gui import app
@@ -21,10 +21,17 @@
2121
write_conn_states_sheet,
2222
write_externals_sheet,
2323
write_inventory_report_sheet,
24+
write_snmp_sheet,
2425
write_stats_sheet,
2526
write_unknown_internals_sheet,
2627
)
27-
from navv.zeek import get_dns_data, run_zeek, perform_zeekcut
28+
from navv.zeek import (
29+
get_conn_data,
30+
get_dns_data,
31+
get_snmp_data,
32+
run_zeek,
33+
perform_zeekcut,
34+
)
2835
from navv.utilities import pushd
2936

3037

@@ -69,17 +76,17 @@ def generate(customer_name, output_dir, pcap, zeek_logs):
6976
else:
7077
timer_data["run_zeek"] = "NOT RAN"
7178

72-
# Get zeek data
73-
zeek_data = get_zeek_data(zeek_logs)
79+
# Get zeek data from conn.log, dns.log and snmp.log
80+
zeek_data = get_conn_data(zeek_logs)
81+
snmp_data = get_snmp_data(zeek_logs)
82+
dns_filtered = get_dns_data(customer_name, output_dir, zeek_logs)
7483

7584
# Get dns data for resolution
7685
json_path = os.path.join(output_dir, f"{customer_name}_dns_data.json")
7786

78-
# Get dns data from zeek logs
79-
dns_filtered = get_dns_data(customer_name, output_dir, zeek_logs)
80-
81-
# Get zeek dataframe
87+
# Get zeek dataframes
8288
zeek_df = get_zeek_df(zeek_data, dns_filtered)
89+
snmp_df = get_snmp_df(snmp_data)
8390

8491
# Get inventory report dataframe
8592
inventory_df = get_inventory_report_df(zeek_df)
@@ -109,6 +116,8 @@ def generate(customer_name, output_dir, pcap, zeek_logs):
109116

110117
write_unknown_internals_sheet(unk_int_IPs, wb)
111118

119+
write_snmp_sheet(snmp_df, wb)
120+
112121
auto_adjust_width(wb["Analysis"])
113122

114123
times = (

src/navv/spreadsheet_tools.py

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -400,7 +400,40 @@ def write_inventory_report_sheet(inventory_df, wb):
400400
for cell in ir_sheet[f"{index}:{index}"]:
401401
cell.fill = openpyxl.styles.PatternFill("solid", fgColor="AAAAAA")
402402
auto_adjust_width(ir_sheet, 40)
403-
# ir_sheet.column_dimensions.width = 39 * 1.2
403+
404+
405+
def write_snmp_sheet(snmp_df, wb):
406+
"""Write SNMP log data to excel sheet."""
407+
sheet = make_sheet(wb, "SNMP", idx=4)
408+
sheet.append(
409+
["Src IPv4", "Src Port", "Dest IPv4", "Dest Port", "Version", "Community"]
410+
)
411+
412+
for index, row in enumerate(snmp_df.to_dict(orient="records"), start=2):
413+
# Source IPv4 column
414+
sheet[f"A{index}"].value = row["src_ip"]
415+
416+
# Source Port column
417+
sheet[f"B{index}"].value = row["src_port"]
418+
419+
# Destination IPv4 column
420+
sheet[f"C{index}"].value = row["dst_ip"]
421+
422+
# Destination Port column
423+
sheet[f"D{index}"].value = row["dst_port"]
424+
425+
# Version column
426+
sheet[f"E{index}"].value = row["version"]
427+
428+
# Community column
429+
sheet[f"F{index}"].value = row["community"]
430+
431+
# Add styling to every other row
432+
if index % 2 == 0:
433+
for cell in sheet[f"{index}:{index}"]:
434+
cell.fill = openpyxl.styles.PatternFill("solid", fgColor="AAAAAA")
435+
436+
auto_adjust_width(sheet, 40)
404437

405438

406439
def write_externals_sheet(IPs, wb):

src/navv/zeek.py

Lines changed: 48 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,24 @@
77

88

99
@timeit
10-
def run_zeek(pcap_path, zeek_logs_path, **kwargs):
11-
with pushd(zeek_logs_path):
12-
# can we add Site::local_nets to the zeek call here?
13-
try:
14-
check_call(["zeek", "-C", "-r", pcap_path, "local.zeek"])
15-
except Exception as e:
16-
error_msg(e)
10+
def get_conn_data(zeek_logs):
11+
"""Return a list of Zeek conn.log data."""
12+
return (
13+
perform_zeekcut(
14+
fields=[
15+
"id.orig_h",
16+
"id.resp_h",
17+
"id.resp_p",
18+
"proto",
19+
"conn_state",
20+
"orig_l2_addr",
21+
"resp_l2_addr",
22+
],
23+
log_file=os.path.join(zeek_logs, "conn.log"),
24+
)
25+
.decode("utf-8")
26+
.split("\n")[:-1]
27+
)
1728

1829

1930
@timeit
@@ -31,6 +42,26 @@ def get_dns_data(customer_name, output_dir, zeek_logs):
3142
return trim_dns_data(dns_data)
3243

3344

45+
@timeit
46+
def get_snmp_data(zeek_logs):
47+
"""Get SNMP data from zeek logs or from a json file if it exists"""
48+
return (
49+
perform_zeekcut(
50+
fields=[
51+
"id.orig_h",
52+
"id.orig_p",
53+
"id.resp_h",
54+
"id.resp_p",
55+
"version",
56+
"community",
57+
],
58+
log_file=os.path.join(zeek_logs, "snmp.log"),
59+
)
60+
.decode("utf-8")
61+
.split("\n")[:-1]
62+
)
63+
64+
3465
def perform_zeekcut(fields, log_file):
3566
"""Perform the call to zeek-cut with the identified fields on the specified log file"""
3667
try:
@@ -42,3 +73,13 @@ def perform_zeekcut(fields, log_file):
4273
except OSError as e:
4374
# probably "file does not exist"
4475
return b""
76+
77+
78+
@timeit
79+
def run_zeek(pcap_path, zeek_logs_path, **kwargs):
80+
with pushd(zeek_logs_path):
81+
# can we add Site::local_nets to the zeek call here?
82+
try:
83+
check_call(["zeek", "-C", "-r", pcap_path, "local.zeek"])
84+
except Exception as e:
85+
error_msg(e)

0 commit comments

Comments
 (0)