Skip to content

Commit 7d1c513

Browse files
committed
Merge branch 'next' into 'master'
PAPP-18184: Symantec DLP: Next to Master See merge request phantom-apps/symantecdlp!4
2 parents 9f78d50 + 5e9ee8f commit 7d1c513

File tree

10 files changed

+634
-273
lines changed

10 files changed

+634
-273
lines changed

.gitmodules

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +0,0 @@
1-
[submodule "wheels"]
2-
path = wheels
3-
url = git@cd.splunkdev.com:phantom-external/suds.git
4-
ignore = dirty

__init__.py

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,5 @@
1-
# --
21
# File: __init__.py
2+
# Copyright (c) 2018-2021 Splunk Inc.
33
#
4-
# Copyright (c) Phantom Cyber Corporation, 2018
5-
#
6-
# This unpublished material is proprietary to Phantom Cyber.
7-
# All rights reserved. The methods and
8-
# techniques described herein are considered trade secrets
9-
# and/or confidential. Reproduction or distribution, in whole
10-
# or in part, is forbidden except by express written permission
11-
# of Phantom Cyber Corporation.
12-
#
13-
# --
4+
# SPLUNK CONFIDENTIAL - Use or disclosure of this material in whole or in part
5+
# without a valid written license from Splunk Inc. is PROHIBITED.

exclude_files.txt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
docker-compose.yml
22
Makefile
3-
*.py
4-
.git*
3+
.git*
4+
.gitlab-ci.yml
5+
whitesource-results

parse_incidents.py

Lines changed: 33 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,13 @@
1-
# --
21
# File: parse_incidents.py
2+
# Copyright (c) 2018-2021 Splunk Inc.
33
#
4-
# Copyright (c) Phantom Cyber Corporation, 2018
5-
#
6-
# This unpublished material is proprietary to Phantom Cyber.
7-
# All rights reserved. The methods and
8-
# techniques described herein are considered trade secrets
9-
# and/or confidential. Reproduction or distribution, in whole
10-
# or in part, is forbidden except by express written permission
11-
# of Phantom Cyber Corporation.
12-
#
13-
# --
4+
# SPLUNK CONFIDENTIAL - Use or disclosure of this material in whole or in part
5+
# without a valid written license from Splunk Inc. is PROHIBITED.
146

157

168
import os
17-
import base64
189
import tempfile
10+
from symantecdlp_consts import *
1911
from phantom.app import CONTAINS_VALIDATORS
2012

2113
container_common = {
@@ -32,7 +24,7 @@
3224

3325
def determine_contains(value):
3426
contains = []
35-
for c, f in CONTAINS_VALIDATORS.items():
27+
for c, f in list(CONTAINS_VALIDATORS.items()):
3628
if f(value):
3729
contains.append(c)
3830
return contains
@@ -133,7 +125,7 @@ def parse_network_http_incident(incident, container, artifact):
133125
def parse_network_im_incident(incident, container, artifact):
134126

135127
artifact['name'] = "Instant Message Info"
136-
container['name'] = "Instanct Message at {0}".format(incident['incidentCreationDate'])
128+
container['name'] = "Instant Message at {0}".format(incident['incidentCreationDate'])
137129

138130
return True
139131

@@ -183,11 +175,11 @@ def parse_network_incident(incident_type, incident, container, artifacts):
183175
artifact['cef'] = cef
184176
artifact['cef_types'] = cef_types
185177

186-
for k, v in incident.iteritems():
178+
for k, v in list(incident.items()):
187179
if k in ['policy', 'components', 'originator', 'recipient']:
188180
continue
189181
cef[k] = v
190-
if isinstance(v, basestring):
182+
if isinstance(v, (str, bytes)):
191183
cef_types = determine_contains(v)
192184

193185
parser_dict = {
@@ -259,7 +251,7 @@ def parse_endpoint_http_incident(incident, container, artifact):
259251
def parse_endpoint_im_incident(incident, container, artifact):
260252

261253
artifact['name'] = "Instant Message Info"
262-
container['name'] = "Instanct Message at {0}".format(incident['incidentCreationDate'])
254+
container['name'] = "Instant Message at {0}".format(incident['incidentCreationDate'])
263255

264256
return True
265257

@@ -317,17 +309,17 @@ def parse_endpoint_incident(incident_type, incident, container, artifacts):
317309
artifacts.append(artifact)
318310
artifact.update(artifact_common)
319311
cef = {}
320-
cef_types = {'userName': 'user name'}
312+
cef_types = {'userName': ['user name']}
321313
artifact['cef'] = cef
322314
artifact['cef_types'] = cef_types
323315

324-
for k, v in incident.iteritems():
316+
for k, v in list(incident.items()):
325317
if k in ['policy', 'components', 'originator', 'recipient']:
326318
continue
327319
if k.startswith('machine'):
328320
cef[k.replace('machine', 'device')] = v
329321
cef[k] = v
330-
if isinstance(v, basestring):
322+
if isinstance(v, (str, bytes)):
331323
cef_types = determine_contains(v)
332324

333325
parser_dict = {
@@ -504,17 +496,17 @@ def parse_discover_incident(incident_type, incident, container, artifacts):
504496
artifacts.append(artifact)
505497
artifact.update(artifact_common)
506498
cef = {}
507-
cef_types = {'userName': 'user name'}
499+
cef_types = {'userName': ['user name']}
508500
artifact['cef'] = cef
509501
artifact['cef_types'] = cef_types
510502

511-
for k, v in incident.iteritems():
503+
for k, v in list(incident.items()):
512504
if k in ['policy', 'components', 'originator', 'recipient']:
513505
continue
514506
if k.startswith('machine'):
515507
cef[k.replace('machine', 'device')] = v
516508
cef[k] = v
517-
if isinstance(v, basestring):
509+
if isinstance(v, (str, bytes)):
518510
cef_types = determine_contains(v)
519511

520512
parser_dict = {
@@ -566,13 +558,13 @@ def parse_mobile_incident(incident_type, incident, container, artifacts):
566558
artifact['cef'] = cef
567559
artifact['cef_types'] = cef_types
568560

569-
for k, v in incident.iteritems():
561+
for k, v in list(incident.items()):
570562
if k in ['policy', 'components', 'originator', 'recipient']:
571563
continue
572564
if k.startswith('machine'):
573565
cef[k.replace('machine', 'device')] = v
574566
cef[k] = v
575-
if isinstance(v, basestring):
567+
if isinstance(v, (str, bytes)):
576568
cef_types = determine_contains(v)
577569

578570
if incident_type == 'MobileFTPIncidentDetail':
@@ -611,17 +603,17 @@ def parse_rest_incident(incident_type, incident, container, artifacts):
611603
artifacts.append(artifact)
612604
artifact.update(artifact_common)
613605
cef = {}
614-
cef_types = {'userName': 'user name'}
606+
cef_types = {'userName': ['user name']}
615607
artifact['cef'] = cef
616608
artifact['cef_types'] = cef_types
617609

618-
for k, v in incident.iteritems():
610+
for k, v in list(incident.items()):
619611
if k in ['policy', 'components', 'originator', 'recipient']:
620612
continue
621613
if k.startswith('machine'):
622614
cef[k.replace('machine', 'device')] = v
623615
cef[k] = v
624-
if isinstance(v, basestring):
616+
if isinstance(v, (str, bytes)):
625617
cef_types = determine_contains(v)
626618

627619
if incident_type == 'RestDARIncidentDetail':
@@ -653,7 +645,7 @@ def parse_incident(incident_type, incident, container, artifacts):
653645

654646
def parse_incidents(incidents, base_connector):
655647

656-
if (type(incidents) != list):
648+
if not isinstance(incidents, list):
657649
raise "incidents parameter is not a list"
658650

659651
results = []
@@ -680,7 +672,12 @@ def parse_incidents(incidents, base_connector):
680672
container.update(container_common)
681673

682674
if 'severity' in curr_incident.get('incident', []):
683-
container['severity'] = curr_incident.get('incident', {}).get('severity', 'medium')
675+
container['severity'] = curr_incident.get('incident', {}).get('severity', 'medium').lower()
676+
if container['severity'] in base_connector._severity.keys():
677+
container['severity'] = base_connector._severity[container['severity']]
678+
else:
679+
base_connector.debug_print(DLP_UNKNOWN_SEVERITY.format(key=container['severity']))
680+
container['severity'] = 'medium'
684681

685682
cef = {}
686683
if 'policy' in curr_incident:
@@ -700,35 +697,29 @@ def parse_incidents(incidents, base_connector):
700697
# work on the files if present
701698
components = curr_incident.get('components', [])
702699

703-
if type(components) != list:
700+
if not isinstance(components, list):
704701
components = [components]
705702

706703
for component in components:
707704

708705
content = component.get('content')
709-
if (not content):
706+
if not content:
710707
continue
711708

712709
file_desc, file_path = tempfile.mkstemp(suffix='.comp', prefix='app_dlp', dir='/vault/tmp/')
713710

714711
file_name = component.get('name')
715-
if (not file_name):
712+
if not file_name:
716713
file_name = os.path.split(file_path)[1]
717714

718715
try:
719-
file_contents = base64.b64decode(content)
720-
except Exception as e:
721-
base_connector.debug_print("Unable to decode file content", e)
722-
continue
723-
724-
try:
725-
with open(file_path, 'wb') as file_handle:
726-
file_handle.write(file_contents)
716+
with open(file_path, 'w') as file_handle:
717+
file_handle.write(content)
727718
except Exception as e:
728719
base_connector.debug_print("Unable to save file content", e)
729720
continue
730721

731-
os.chmod(file_path, 0660)
722+
os.chmod(file_path, 0o660)
732723

733724
file_info = {'file_path': file_path, 'file_name': file_name}
734725

readme.html

Lines changed: 45 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,48 @@
1-
<!--
2-
File: readme.html
1+
<!-- File: readme.html
2+
Copyright (c) 2018-2021 Splunk Inc.
33
4-
Copyright (c) Phantom Cyber Corporation, 2018
5-
6-
This unpublished material is proprietary to Phantom Cyber.
7-
All rights reserved. The methods and
8-
techniques described herein are considered trade secrets
9-
and/or confidential. Reproduction or distribution, in whole
10-
or in part, is forbidden except by express written permission
11-
of Phantom Cyber.
4+
SPLUNK CONFIDENTIAL - Use or disclosure of this material in whole or in part
5+
without a valid written license from Splunk Inc. is PROHIBITED.
126
-->
13-
14-
<p>
7+
<h2>On Poll</h2>
158
<h3>Ingestion</h3>
16-
During the first scheduled poll, all incidents that fall in the <b>first_scheduled_ingestion_span</b> will be ingested.
17-
<br><br>
18-
During a <b>POLL NOW</b>, incidents will be ingested starting with the most recent. The number of incidents ingested will depend on the specified <b>max_containers</b> and <b>poll_now_ingestion_span</b>, whichever limit is hit first.
19-
</p>
9+
10+
<h4> Schedule | Interval Polling </h4>
11+
<ul>
12+
<li>During scheduled | interval polling, the app will start from the number of days specified in <b>first_scheduled_ingestion_span</b> and will ingest up to the number of incidents specified in the <b>max_containers</b> (Default value 10) in configuration parameter per cycle. Then it remembers the last ingested 'incident_id' and stores it in the state file against the key 'last_incident_ingested'. For the next scheduled | interval cycles, ingestion will start from the last_incident_ingested in the state file and will ingest up to the number of incidents specified in the <b>max_containers</b>.</li>
13+
<li>The number of incidents ingested will depend on the specified <b>max_containers</b> and <b>poll_now_ingestion_span</b>, whichever limit is hit first.</li>
14+
</ul>
15+
<h4> Manual Polling </h4>
16+
<ul>
17+
<li>
18+
During a <b>POLL NOW</b>, incidents will be ingested starting with the oldest first. The number of incidents ingested will depend on the specified <b>max_containers</b> and <b>poll_now_ingestion_span</b>, whichever limit is hit first.
19+
</li>
20+
</ul>
21+
<b>Custom Severity Config Parameter</b>
22+
<ul>
23+
<li>
24+
It is an optional parameter. Here the user needs to provide a JSON string in the following format
25+
<br>{'symantecdlp_severity': 'phantom_severity'}<br>
26+
This parameter can be used to map the Symantec DLP incident severity to any of the custom phantom severity.
27+
</li>
28+
<li>
29+
To configure a custom severity in the Phantom, go to Administrator → Event Settings → Severity. Click on 'add item' and give an appropriate name for the severity and click on 'Done' button.
30+
</li>
31+
<li>
32+
By default, the severity is mapped in the following way:
33+
<ul>
34+
<li>
35+
For the incident having 'high' severity, the container's severity will be 'high'.
36+
</li>
37+
<li>
38+
For the incident having 'medium' severity, the container's severity will be 'medium'.
39+
</li>
40+
<li>
41+
For the incident having 'low' severity, the container's severity will be 'low'.
42+
</li>
43+
<li>
44+
For the incident having severity other than 'high', 'low' or 'medium' the container's severity will be 'medium'.
45+
</li>
46+
</ul>
47+
</li>
48+
</ul>

requirements.txt

Whitespace-only changes.

0 commit comments

Comments
 (0)