forked from alphagov-mirror/cyber-security-nessus
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathprocess_scans.py
More file actions
99 lines (74 loc) · 2.66 KB
/
process_scans.py
File metadata and controls
99 lines (74 loc) · 2.66 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
import csv
import io
from functools import lru_cache
import boto3
from nessus import download_report, list_scans, prepare_export
def find_scans():
scans = list_scans()
for scan in scans["scans"]:
# This is for testing as we haven't run a full scan yet
if scan["status"] == "completed":
print(f"Preparing export for {scan['name']}")
token = prepare_export(scan["id"])
csv_text = download_report(token)
process_csv(csv_text, scan)
elif scan["status"] == "empty":
print(f"Scan {scan['name']} has not run.")
def process_csv(csv_text, scan):
"""
Send the CSV - 1 row at a time - to cloud watch. This will create a
new event for each row in Splunk.
"""
# Need to use StringIO because csv.reader expects a file object
with io.StringIO(csv_text) as f:
reader = csv.reader(f)
group_name = "/gds/nessus-data"
stream_name = f"{scan['last_modification_date']}-{scan['name']}"
token = create_log_stream(group_name, stream_name)
events = []
for row in reader:
events.append(
{
"timestamp": scan["last_modification_date"] * 1000,
"message": ",".join(row).replace("\n", " "),
}
)
# Send in batches of 10_000
if len(events) >= 9999:
token = logs_client().put_log_events(
logGroupName="/gds/nessus-data",
logStreamName=stream_name,
logEvents=events,
sequenceToken=token,
)["nextSequenceToken"]
events = []
# send finial batch
logs_client().put_log_events(
logGroupName="/gds/nessus-data",
logStreamName=stream_name,
logEvents=events,
sequenceToken=token,
)
@lru_cache(maxsize=None)
def logs_client():
return boto3.client("logs")
def create_log_stream(group_name, stream_name):
try:
logs_client().create_log_stream(
logGroupName=group_name, logStreamName=stream_name
)
except logs_client().exceptions.ResourceAlreadyExistsException:
pass
response = logs_client().describe_log_streams(
logGroupName=group_name, logStreamNamePrefix=stream_name,
)
if "uploadSequenceToken" in response["logStreams"][0]:
token = response["logStreams"][0]["uploadSequenceToken"]
else:
token = "0"
return token
def main(event, context):
print("Processing scans and sending to cloudwatch...")
find_scans()
if __name__ == "__main__":
main(None, None)