DBotSuggestClassifierMapping
Deprecated. No available replacement. Suggests a classifier mapping based on an advanced name matching algorithm.
- Type
- python
- Pack
- Base
Source
from CommonServerPython import *
import itertools
import numbers
import re
import socket
from collections import Counter
from collections import OrderedDict
from datetime import datetime, timedelta
INCIDENT_FIELD_NAME = "name"
INCIDENT_FIELD_MACHINE_NAME = "cliName"
INCIDENT_FIELD_SYSTEM = "system"
INCIDENT_FIELD_UNMAPPED = "unmapped"
SAMPLES_INCOMING = 'incomingSamples'
SAMPLES_SCHEME = 'scheme'
SAMPLES_OUTGOING = 'outgoingSamples'
COUNT_KEYWORD = "count"
SIEM_FIELDS = {'Account ID': {'aliases': ['accountid', 'account id'],
'validators': []},
'Account Name': {'aliases': ['accountname', 'account name'],
'validators': ['validate_alphanumeric_with_common_punct']},
'Account Type': {'aliases': ['accounttype', 'account type'],
'validators': ['validate_alphanumeric_with_common_punct']},
'Agent ID': {'aliases': ['agentid', 'agent id', 'sensor id', 'tenant id'],
'validators': []},
'Tenant Name': {'aliases': ['tenant name', 'tenant name'],
'validators': ['validate_alphanumeric_with_common_punct']},
'App': {'aliases': ['app', 'app'], 'validators': ['validate_alphanumeric_with_common_punct']},
'Attachment Name': {'aliases': ['attachmentname', 'attachment name'],
'validators': ['validate_alphanumeric_with_common_punct']},
'Blocked Action': {'aliases': ['blockedaction', 'blocked action', 'prevention mode'],
'validators': ['validate_alphanumeric_with_common_punct']},
'City': {'aliases': ['city'], 'validators': ['validate_alphanumeric_with_common_punct']},
'Command Line': {'aliases': ['commandline', 'command line', 'cmdline', 'cmd line', 'process file name',
'process file path',
'process full path', 'process full path', 'cmd'],
'validators': ['validate_file_full_path']},
'Event ID': {'aliases': ['eventid', 'event id', 'alert id', 'offense id'],
'validators': ['validate_alphanumeric_with_common_punct']},
'Event Type': {'aliases': ['eventtype', 'event type', 'alert type'],
'validators': ['validate_alphanumeric_with_common_punct']},
'Company Name': {'aliases': ['companyname',
'company name',
'company',
'customer'],
'validators': ['validate_alphanumeric_with_common_punct']},
'Country': {'aliases': ['country', 'country name'],
'validators': ['validate_alphanumeric_with_common_punct']},
'Critical Assets': {'aliases': ['criticalassets', 'critical assets'],
'validators': ['validate_alphanumeric_with_common_punct']},
'Description': {'aliases': ['description'], 'validators': ['validate_alphanumeric_with_common_punct']},
'Destination IP': {'aliases': ['destinationip',
'destination ip',
'destination address',
'dest ip',
'dest address',
'target address',
'dst'],
'validators': ['validate_ip']},
'Destination Port': {'aliases': ['destinationport',
'destination port',
'dst port',
'dest port'],
'validators': ['validate_number']},
'Email BCC': {'aliases': ['emailbcc', 'email bcc', 'bcc recipient', 'bcc'],
'validators': ['validate_email']},
'Email Body': {'aliases': ['emailbody', 'email body', 'body'],
'validators': []},
'Email Body Format': {'aliases': ['emailbodyformat',
'email body format',
'body type',
'body content type'],
'validators': []},
'Email Body HTML': {'aliases': ['emailbodyhtml', 'email body html'],
'validators': []},
'Email CC': {'aliases': ['emailcc', 'email cc', 'cc recipient', 'cc'],
'validators': ['validate_email']},
'Email From': {'aliases': ['emailfrom', 'email from', 'from'],
'validators': ['validate_email']},
'Email HTML': {'aliases': ['emailhtml', 'email html'], 'validators': []},
'Email Headers': {'aliases': ['emailheaders', 'email headers', 'headers', 'message headers',
'internet message header'],
'validators': ['']},
'Email In Reply To': {'aliases': ['emailinreplyto', 'email in reply to'],
'validators': []},
'Email Received': {'aliases': ['emailreceived',
'email received',
'received date time',
'received time'],
'validators': ['validate_date']},
'Email Reply To': {'aliases': ['emailreplyto', 'email replay to', 'reply to'],
'validators': []},
'Email Sender IP': {'aliases': ['emailsenderip', 'email sender ip'],
'validators': ['validate_ip']},
'Email Size': {'aliases': ['emailsize', 'email size'], 'validators': ['validate_number']},
'Email Subject': {'aliases': ['emailsubject', 'email subject', 'subject'],
'validators': []},
'Email To': {'aliases': ['emailto',
'email to',
'to recipients',
'recipients',
'recipient'],
'validators': ['validate_email']},
'File Hash': {'aliases': ['filehash', 'file hash', 'event file hash', 'md5', 'sha1', 'sha256'],
'validators': ['validate_hash']},
'File Name': {'aliases': ['filename', 'file name'], 'validators': []},
'File Path': {'aliases': ['filepath', 'file path', 'full path', 'full path'],
'validators': ['validate_file_full_path']},
'File Size': {'aliases': ['filesize', 'file size'], 'validators': ['validate_number']},
'File Type': {'aliases': ['filetype', 'file type'],
'validators': ['validate_alphanumeric_with_common_punct']},
'Source Hostname': {
'aliases': ['source hostname', 'source host name', 'src hostname', 'src host name'],
'validators': ['validate_hostname']},
'Destination Hostname': {
'aliases': ['destination hostname', 'destination host name',
'dest hostname', 'dest host name', 'dst hostname', 'dst host name',
'target hostname', 'target host name'],
'validators': ['validate_hostname']},
'Source Network': {'aliases': ['source network', 'sourcenetwork', 'src network'],
'validators': ['validate_alphanumeric_with_common_punct']},
'Destination Network': {'aliases': ['destination network', 'destinationnetwork',
'dest network', 'dst network', 'target netwrok'],
'validators': ['validate_alphanumeric_with_common_punct']},
'Device Name': {
'aliases': ['devicename', 'device name', 'endpoint name', 'end point name'],
'validators': ['validate_alphanumeric_with_common_punct']},
'MAC Address': {'aliases': ['macaddress', 'mac address', 'mac', 'src mac', 'source mac'],
'validators': ['validate_mac']},
'PID': {'aliases': ['pid', 'process pid', 'parent process pid', 'target process pid'],
'validators': ['validate_number']},
'Parent Process ID': {'aliases': ['parentprocessid', 'parent process id'],
'validators': ['validate_number']},
'Region': {'aliases': ['region', 'region'], 'validators': ['validate_alphanumeric_with_common_punct']},
'Signature': {'aliases': ['signature', 'signature'], 'validators': []},
'Source IP': {
'aliases': ['sourceip', 'source ip', 'src ip', 'src address', 'source address', 'computer ip',
'device ip',
'attacker address', 'attacker ip', 'sender ip', 'sender address', 'agent ip'],
'validators': ['validate_ip']},
'Source Port': {'aliases': ['sourceport',
'source port',
'src port'],
'validators': ['validate_number']},
'OS': {'aliases': ['operating system', 'os type', 'os version', 'os'],
'validators': []},
'Subtype': {'aliases': ['subtype', 'subtype'],
'validators': ['validate_alphanumeric_with_common_punct']},
'Terminated Action': {'aliases': ['terminatedaction', 'terminated action'],
'validators': []},
'Traps ID': {'aliases': ['trapsid', 'traps id', 'trap id'], 'validators': []},
'Source Username': {'aliases': ['username', 'username', 'user name', 'src user name',
'src username', 'source username', 'source user name'],
'validators': ['validate_alphanumeric_with_common_punct']},
'Destination Username': {'aliases': ['destination username', 'destination user name',
'dest username', 'dest user name', 'dst username', 'dst user name',
'target user name', 'target username'],
'validators': ['validate_alphanumeric_with_common_punct']},
'Detection URL': {'aliases': ['detection url'],
'validators': ['validate_url']},
'Vendor ID': {'aliases': ['vendorid', 'vendor id'], 'validators': []},
'Vendor Product': {'aliases': ['vendorproduct', 'vendor product'],
'validators': ['validate_alphanumeric_with_common_punct']},
'category': {'aliases': ['category', 'category'],
'validators': ['validate_alphanumeric_with_common_punct']},
'details': {'aliases': ['details', 'description'],
'validators': ['validate_alphanumeric_with_common_punct']},
'name': {'aliases': ['name', 'Name', 'alert name', 'event name', 'rule name', 'title'],
'validators': ['validate_alphanumeric_with_common_punct', 'extact_name_math']},
'occurred': {'aliases': ['occurred', 'occured', 'occurred time', 'event start time', 'event at',
'event time', 'start time',
'create time', 'timestamp', 'unix time', 'click time'],
'validators': ['validate_date']},
'owner': {'aliases': ['owner'], 'validators': []},
'severity': {'aliases': ['event severity', 'severity', 'event priority', 'priority', 'urgency'],
'validators': []},
'Log Source': {'aliases': ['log source', 'log sources', 'logsource'], 'validators': []},
'Protocol': {'aliases': ['protocol'], 'validators': []},
}
suffix_mapping = {
'ing': '',
'ly': '',
'ed': '',
'ious': '',
'ies': 'y',
'ive': '',
'es': '',
's': ''
}
class DateValidator:
def __init__(self):
year_options = ['%y', '%Y']
months_options = ['%m', '%B']
day_options = ['%d']
delimeters_options = [".", "-", "/", "\\"]
self.common_separators = [' ', 'T', ',']
date_formats_options = [] # type: List[tuple]
for delimeter in delimeters_options:
delimeters = [delimeter]
date_formats_options += list(
itertools.product(year_options, delimeters, months_options, delimeters, day_options))
date_formats_options += list(
itertools.product(year_options, delimeters, day_options, delimeters, months_options))
date_formats_options += list(
itertools.product(day_options, delimeters, months_options, delimeters, year_options))
date_formats_options += list(
itertools.product(day_options, delimeters, months_options, delimeters, year_options))
self.date_formats_options = list(map(lambda x: "".join(x), date_formats_options))
def try_parsing_date(self, text):
for fmt in self.date_formats_options:
try:
return datetime.strptime(text, fmt)
except ValueError:
pass
return None
def has_valid_date(self, text):
parts = [] # type: List[str]
for sep in self.common_separators:
parts += text.split(sep)
return any(map(lambda x: self.try_parsing_date(x) is not None, parts))
@staticmethod
def is_datetime_last_years(d, number_of_years=3):
if d is not None:
now = datetime.now()
return now - timedelta(days=365 * number_of_years) <= d <= now + timedelta(days=365 * number_of_years)
return False
@staticmethod
def safe_parse_timestamp(value):
try:
d = datetime.fromtimestamp(int(value))
return d
except Exception:
return None
def is_unix_timestamp(self, value):
try:
value = int(value)
return self.is_datetime_last_years(self.safe_parse_timestamp(value)) or self.is_datetime_last_years(
self.safe_parse_timestamp(value / 1000))
except Exception:
return False
class Validator:
def __init__(self):
self.EMAIL_REGEX = re.compile('^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$')
self.NUMBER_REGEX = re.compile('^([0-9]+)$')
self.SHA256_REGEX = re.compile('^[A-Fa-f0-9]{64}$')
self.MD5_REGEX = re.compile('^[a-fA-F0-9]{32}$')
self.HASH_REGEX = re.compile('^[a-fA-F0-9]+$')
self.MAC_REGEX = re.compile('^[0-9a-f]{2}([-:]?)[0-9a-f]{2}(\\1[0-9a-f]{2}){4}$', re.IGNORECASE)
self.URL_REGEX = re.compile(
r'^(?:http|ftp|hxxp)s?://' # http:// or https://
r'(?:(?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\.)+(?:[A-Z]{2,6}\.?|[A-Z0-9-]{2,}\.?)|' # domain...
r'localhost|' # localhost...
r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})' # ...or ip
r'(?::\d+)?' # optional port
r'(?:/?|[/?]\S+)$', re.IGNORECASE)
self.COMMON_NAME_CHARECTERS = re.compile('^[0-9a-zA-Z"\s_\-\'./]+$')
self.HOSTNAME_PART_REGEX = re.compile('(?!-)[A-Z\d-]{1,63}(?<!-)$')
self.FULL_FILE_PATH_REGEX = re.compile('^((?:/[^/\n]+)*|.*(\\\\.*))$')
self.date_validator = DateValidator()
def validate_regex(self, pattern, value, json_field_name=None):
if isinstance(value, str):
return pattern.match(value) is not None
return False
def validate_ip(self, field_name, value, json_field_name=None):
try:
socket.inet_aton(value)
return True
except socket.error:
return False
def validate_url(self, field_name, value, json_field_name=None):
return self.validate_regex(self.URL_REGEX, value)
def validate_email(self, field_name, value, json_field_name=None):
return self.validate_regex(self.EMAIL_REGEX, value)
def validate_number(self, field_name, value, json_field_name=None):
if isinstance(value, numbers.Number):
return True
else:
return self.validate_regex(self.NUMBER_REGEX, value, json_field_name=None)
def validate_not_count(self, field_name, value):
is_count = COUNT_KEYWORD in field_name.lower() and self.validate_number(field_name, value)
return not is_count
def validate_sha256(self, field_name, value, json_field_name=None):
return self.validate_regex(self.SHA256_REGEX, value)
def validate_md5(self, field_name, value, json_field_name=None):
return self.validate_regex(self.MD5_REGEX, value)
def validate_hash(self, field_name, value, json_field_name=None):
return self.validate_regex(self.HASH_REGEX, value) and len(value) % 2 == 0
def validate_mac(self, field_name, value, json_field_name=None):
return self.validate_regex(self.MAC_REGEX, value)
def validate_hostname(self, field_name, hostname, json_field_name=None):
if not isinstance(hostname, str) or len(hostname) > 255: # type: ignore
return False
if hostname[-1] == ".": # type: ignore
hostname = hostname[:-1] # type: ignore
allowed = re.compile("(?!-)[A-Z\d-]{1,63}(?<!-)$", re.IGNORECASE)
return all(allowed.match(x) for x in hostname.split("."))
def validate_date(self, field_name, value, json_field_name=None):
if self.validate_number("", value):
return self.date_validator.is_unix_timestamp(value)
else:
return self.date_validator.has_valid_date(value)
def validate_alphanumeric_with_common_punct(self, field_name, value, json_field_name=None):
return self.validate_regex(self.COMMON_NAME_CHARECTERS, value)
def validate_file_full_path(self, field_name, value, json_field_name=None):
return self.validate_regex(self.FULL_FILE_PATH_REGEX, value)
def extact_name_math(self, field_name, value, json_field_name=None):
return field_name == json_field_name
def validate(self, validator_name, field_name, value, json_field_name=None):
validate_func = getattr(self, validator_name)
return validate_func(field_name, value, json_field_name)
def is_sublist_of_list(s, lst):
sub_set = False
if s == []:
sub_set = True
elif s == lst:
sub_set = True
elif len(s) > len(lst):
sub_set = False
else:
for i in range(len(lst)):
if lst[i] == s[0]:
n = 1
while (n < len(s)) and (i + n) < len(lst) and (lst[i + n] == s[n]):
n += 1
if n == len(s):
sub_set = True
return sub_set
def lemma_word(word):
for suffix in suffix_mapping:
if word.endswith(suffix):
candidate = word[:-len(suffix)] + suffix_mapping[suffix]
if candidate in ALL_POSSIBLE_TERMS_SET or candidate.lower() in ALL_POSSIBLE_TERMS_SET:
return candidate.lower()
return word.lower()
def remove_dups(seq):
return list(OrderedDict.fromkeys(seq))
def split_by_non_alpha_numeric(_string):
return list(filter(lambda x: x, re.split('[^a-zA-Z0-9]', _string)))
def camel_case_split(identifier):
matches = re.finditer('.+?(?:(?<=[a-z])(?=[A-Z])|(?<=[A-Z])(?=[A-Z][a-z])|$)', identifier)
return [m.group(0) for m in matches]
def flatten_json(y):
out = {}
has_more_than_one_value = []
delimeter = '.'
def flatten(x, name=''):
if type(x) is dict:
for a in x:
flatten(x[a], name + a + delimeter)
elif type(x) is list and len(x) > 0 and type(x) is not dict:
i = 0
for a in x:
flatten(a, name + "[" + str(i) + "]" + delimeter)
i += 1
if i > 1:
has_more_than_one_value.append(name[:-1])
else:
out[name[:-1]] = x
flatten(y)
return out, has_more_than_one_value
def number_of_terms(value):
return len(value.split(" "))
def normilize(value):
parts = [] # type: List[str]
for part in split_by_non_alpha_numeric(value):
parts += camel_case_split(part)
terms = list(map(lemma_word, parts))
return remove_dups(terms)
def validate_value_with_validator(alias, value, json_field_name=None):
field_name = ALIASING_MAP[alias]
validators = SIEM_FIELDS[field_name]['validators'] # type: ignore
validators = [v for v in validators if v]
if len(validators) == 0:
return True
validator_results = []
for validator_name in validators:
validator_results.append(VALIDATOR.validate(validator_name, alias, value, json_field_name))
return all(validator_results)
def get_candidates(json_field_name):
json_field_terms = normilize(json_field_name)
aliases_terms = ALIASING_TERMS_MAP.items()
match_terms = list(map(lambda x: x[0],
filter(lambda alias_terms: is_sublist_of_list(alias_terms[1], json_field_terms),
aliases_terms)))
return sorted(match_terms, reverse=True, key=number_of_terms)
def suggest_field_with_alias(json_field_name, json_field_value=None):
norm_json_field_name = " ".join(normilize(json_field_name))
candidates = get_candidates(json_field_name)
if json_field_value is not None:
candidates = list(filter(lambda c: validate_value_with_validator(c, json_field_value, norm_json_field_name),
candidates))
if len(candidates) > 0:
alias = candidates[0]
return ALIASING_MAP[alias], alias
return None, None
def suggest_field(json_field_name, json_field_value=None):
return suggest_field_with_alias(json_field_name, json_field_value)[0]
def generate_aliases(field):
aliases = []
aliases.append(field.lower())
aliases.append(" ".join(normilize(field)))
aliases.append("".join(normilize(field)))
return aliases
def get_aliasing(siem_fields):
aliasing_map = {}
aliases_terms_map = {}
for field, data in siem_fields.items():
for alias in data['aliases']:
aliasing_map[alias] = field
aliases_terms_map[alias] = alias.split(" ")
return aliasing_map, aliases_terms_map
def is_value_substring_of_one_values(value, all_values):
return any(map(lambda field: value in field, all_values))
def get_alias_index(field_name, alias):
return SIEM_FIELDS[field_name]['aliases'].index(alias) # type: ignore
def get_most_relevant_json_field(field_name, json_field_to_alias):
if len(json_field_to_alias) == 0:
return
# calculate jaccard score for each alias, and get the candidates with max score
scores = {}
for json_field, alias in json_field_to_alias.items():
scores[json_field] = jaccard_similarity_for_string_terms(json_field, alias)
scores = {k: v for k, v in scores.items() if v == max(scores.values())}
# calculate jaccard score for each field, and get the candidates with max score
for json_field, alias in json_field_to_alias.items():
scores[json_field] = jaccard_similarity_for_string_terms(json_field, field_name)
scores = {k: v for k, v in scores.items() if v == max(scores.values())}
# for candidates with the same score with the least alias index
candidates = sorted(list(scores.keys()),
key=lambda json_field: get_alias_index(field_name, json_field_to_alias[json_field]))
return candidates[0]
def match_for_incident(incident_to_match):
flat_incident, more_than_one_field_items = flatten_json(incident_to_match)
incident = {k: v for k, v in flat_incident.items()
if not is_value_substring_of_one_values(k, more_than_one_field_items)}
if SCHEME_ONLY:
incident = {k: v for k, v in incident.items() if not k.endswith(COUNT_KEYWORD)}
else:
incident = {k: v for k, v in incident.items() if v is not None and VALIDATOR.validate_not_count(k, v)}
mapping = {} # type: ignore
for json_field_name, json_field_value in incident.items():
# we try to get suggestion if it's scheme or if the value is not empty
if SCHEME_ONLY or json_field_value:
incident_field_suggestion, alias = suggest_field_with_alias(json_field_name, json_field_value)
if incident_field_suggestion:
if incident_field_suggestion not in mapping:
mapping[incident_field_suggestion] = {}
mapping[incident_field_suggestion][json_field_name] = alias
return {incident_field_name: get_most_relevant_json_field(incident_field_name, json_field_to_alias) for
incident_field_name, json_field_to_alias in mapping.items()}
def jaccard_similarity(list1, list2):
intersection = len(list(set(list1).intersection(list2)))
union = (len(list1) + len(list2)) - intersection
return float(intersection) / union
def jaccard_similarity_for_string_terms(str1, str2):
return jaccard_similarity(normilize(str1), normilize(str2))
def get_most_relevant_match_for_field(field_name, cnt):
# return exact match
if field_name in cnt:
return field_name
suggestions_with_jaccard_score = [(suggestion, jaccard_similarity_for_string_terms(field_name, suggestion)) for
suggestion in cnt.keys()]
suggestions_with_jaccard_score = sorted(suggestions_with_jaccard_score, key=lambda x: x[1], reverse=True)
# check for extact terms
if suggestions_with_jaccard_score[0][1] == 1:
return suggestions_with_jaccard_score[0][0]
# if we have only scheme or all the values are the same
if SCHEME_ONLY or len(set(cnt.values())) == 1:
return suggestions_with_jaccard_score[0][0]
return cnt.most_common()[0][0]
def match_for_incidents(incidents_to_match):
fields_cnt = {} # type: Dict[str, Counter]
for flat_incident in incidents_to_match:
for k, v in match_for_incident(flat_incident).items():
if k not in fields_cnt:
fields_cnt[k] = Counter()
if v:
fields_cnt[k][v] += 1
mapping_result = {field_name: get_most_relevant_match_for_field(field_name, field_cnt) for field_name, field_cnt in
fields_cnt.items()}
return mapping_result
def format_value_to_mapper(json_field):
parts = json_field.split('.', 1)
root = parts[0]
accessor = ""
if len(parts) > 1:
accessor = parts[1]
res = {
"simple": "",
"complex": {
"root": root,
"accessor": accessor,
"filters": [],
"transformers": []
}
}
return res
def format_incident_field_to_mapper(incident_field_name, field_name_to_machine_name):
res = {
"simple": "",
"complex": {
"root": field_name_to_machine_name[incident_field_name],
"accessor": "",
"filters": [],
"transformers": []
}
}
return res
def verify_non_empty_values_in_incidents(expression, incidents):
for incident in incidents:
res = demisto.dt(incident, expression)
if res:
return True
return False
def get_complex_value_key(complex_value):
if 'complex' in complex_value:
complex_value = complex_value['complex']
readable_value = complex_value.get('root')
if complex_value.get('accessor'):
readable_value += "." + complex_value.get('accessor')
return readable_value
def combine_mappers(original_mapper, new_mapper, incidents):
mapper = new_mapper
if original_mapper:
mapper.update(original_mapper)
return mapper
def filter_by_dict_by_keys(_dict, keys):
return {k: v for k, v in _dict.items() if k in keys}
def parse_incident_sample(sample):
if type(sample) is dict and 'rawJSON' in sample:
incident = json.loads(sample['rawJSON'])
else:
try:
incident = json.loads(sample)
except Exception:
incident = sample
return incident
SCHEME_ONLY = False
VALIDATOR = Validator()
ALIASING_MAP, ALIASING_TERMS_MAP, FIELD_NAME_TO_CLI_NAME = {}, {}, {}
ALL_POSSIBLE_TERMS_SET = set()
def init():
global SCHEME_ONLY, VALIDATOR, \
ALIASING_MAP, ALIASING_TERMS_MAP, \
ALL_POSSIBLE_TERMS_SET, SIEM_FIELDS, FIELD_NAME_TO_CLI_NAME
SCHEME_ONLY = demisto.args().get('incidentSamplesType') in [SAMPLES_OUTGOING, SAMPLES_SCHEME]
fields = demisto.args().get('incidentFields', {})
fields = [x for x in fields if not x.get(INCIDENT_FIELD_UNMAPPED, False)]
if fields and len(fields) > 0:
fields_names = list(map(lambda x: x['name'], fields))
SIEM_FIELDS = filter_by_dict_by_keys(SIEM_FIELDS, fields_names)
for custom_field in filter(lambda x: not x['system'], fields):
field_name = custom_field[INCIDENT_FIELD_NAME]
SIEM_FIELDS[field_name] = {'aliases': generate_aliases(field_name), 'validators': []}
FIELD_NAME_TO_CLI_NAME = {field[INCIDENT_FIELD_NAME]: field[INCIDENT_FIELD_MACHINE_NAME] for field in fields}
ALIASING_MAP, ALIASING_TERMS_MAP = get_aliasing(SIEM_FIELDS)
terms = [] # type: List[str]
for field in SIEM_FIELDS.values():
for alias in field['aliases']: # type: ignore
terms += alias.split(" ")
ALL_POSSIBLE_TERMS_SET = set(terms)
def main():
init()
incidents_samples = demisto.args().get('incidentSamples')
if incidents_samples:
if isinstance(incidents_samples, str):
incidents_samples = json.loads(incidents_samples) # type: ignore
incidents = list(map(parse_incident_sample, incidents_samples))
else:
return_error("Could not parse incident samples")
original_mapper = demisto.args().get('currentMapper')
if type(original_mapper) is not dict or len(original_mapper) == 0:
original_mapper = None
matches = match_for_incidents(incidents)
if demisto.args().get('incidentSamplesType') == SAMPLES_OUTGOING:
mapper = {v: format_incident_field_to_mapper(k, FIELD_NAME_TO_CLI_NAME) for k, v in matches.items() if
k in FIELD_NAME_TO_CLI_NAME}
else:
mapper = {k: format_value_to_mapper(v) for k, v in matches.items()}
mapper = combine_mappers(original_mapper, mapper, incidents)
return mapper
if __name__ in ['__main__', '__builtin__', 'builtins']:
demisto.results(main())