Skip to content

Commit

Permalink
Merge branch 'master' of github.com:demisto/content into MSDE_PB_Isol…
Browse files Browse the repository at this point in the history
…ate_Unisolate_device
  • Loading branch information
ssokolovich committed Dec 8, 2021
2 parents 44e5257 + 15d227d commit d4c2f9b
Show file tree
Hide file tree
Showing 6 changed files with 549 additions and 1 deletion.
4 changes: 4 additions & 0 deletions Packs/QRadar/ReleaseNotes/2_1_19.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@

#### Scripts
##### New: QRadarCreateAQLQuery
- Build QRadar AQL Query. (Available from Cortex XSOAR 6.0.0).
123 changes: 123 additions & 0 deletions Packs/QRadar/Scripts/QRadarCreateAQLQuery/QRadarCreateAQLQuery.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
import demistomock as demisto # noqa: F401
from CommonServerPython import * # noqa: F401
from enum import Enum
from typing import Dict, List


REPLACE_KEYS = [
('base_values_to_search', 'base_additional_values'),
('base_fields_to_search', 'base_additional_fields'),
('base_field_state', 'base_additional_field_state'),
('base_field_match', 'base_additional_field_match')
]


class SectionNotFound(Exception):
pass


class Operators(Enum):
OR = 'OR'
AND = 'AND'


class MatchRule(Enum):
EQUAL = "{} = '{}'"
NOT_EQUAL = "{} != '{}'"
ILIKE = "{} ILIKE '%{}%'"
NOT_ILIKE = "{} NOT ILIKE '%{}%'"


def fields_section(fields_list: List[str], values_list: List[str], operator: Operators = Operators.OR,
match_rule: MatchRule = MatchRule.EQUAL) -> str:
condition_list: List[str] = []
for field in map(lambda x: x if ' ' not in x else f"'{x}'", fields_list):
for value in values_list:
condition_list.append(match_rule.value.format(field, value))

return f"({f' {operator.value} '.join(condition_list)})"


def complete_query(select_fields: str, combined_sections: str, time_frame: str) -> str:
return f"select {select_fields} from events where {combined_sections} {time_frame}"


def prepare_section(args: Dict, section_prefix: str) -> Dict:
try:
values_list = argToList(args[f'{section_prefix}_additional_values'])
except KeyError:
raise SectionNotFound(section_prefix)
fields_list = args.get(f'{section_prefix}_additional_fields')
if args[f'{section_prefix}_additional_field_match'] == 'partial':
if args[f'{section_prefix}_additional_field_state'] == 'include':
match_rule = MatchRule.ILIKE
else:
match_rule = MatchRule.NOT_ILIKE
fields_list = fields_list or ['UTF8(payload)']
else:
if not fields_list:
raise KeyError(f'{section_prefix}_additional_fields')
if args[f'{section_prefix}_additional_field_state'] == 'include':
match_rule = MatchRule.EQUAL
else:
match_rule = MatchRule.NOT_EQUAL

return {
'values_list': values_list,
'match_rule': match_rule,
'fields_list': argToList(fields_list)
}


def prepare_args(args: Dict) -> Dict:
for key in list(args):
if not args[key]:
args.pop(key)
for original_key, new_key in REPLACE_KEYS:
try:
args[new_key] = args.pop(original_key)
except KeyError:
# ignore the key beacuse a part of them are not required and we already handeling the key errors in the main function
pass
return args


def original_key_name(key_name) -> str:
for original_key, new_key in REPLACE_KEYS:
if key_name == new_key:
return original_key

return key_name


def create_sections_str(args: Dict[str, str], operator: Operators = Operators.AND) -> str:
sections = []
for section_prefix in ['base', 'first', 'second']:
try:
sections.append(fields_section(**prepare_section(args, section_prefix)))
except SectionNotFound:
if section_prefix == 'base':
raise DemistoException('base arguments not given correctly')
return f' {operator.value} '.join(sections)


def main():
try:
args = prepare_args(demisto.args())
time_frame = args['time_frame']
select_fields = args['select_fields']
aql_string = complete_query(
select_fields=select_fields,
combined_sections=create_sections_str(args),
time_frame=time_frame,
)
return_results(CommandResults(readable_output=aql_string, outputs={'QRadarQuery': aql_string}))
except KeyError as key_error:
key_name = original_key_name(key_error.args[0])
return_error(f'Missing {key_name}.')
except Exception as error:
return_error(str(error), error)


if __name__ in ('__main__', '__builtin__', 'builtins'):
main()
107 changes: 107 additions & 0 deletions Packs/QRadar/Scripts/QRadarCreateAQLQuery/QRadarCreateAQLQuery.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
commonfields:
id: QRadarCreateAQLQuery
version: -1
name: QRadarCreateAQLQuery
script: ''
type: python
tags:
- Utility
comment: Build QRadar AQL Query.
args:
- name: base_values_to_search
required: true
isArray: true
description: The values of the first field to search. This can be a single value
or a comma-separated list of values. For example admin1,admin2.
- name: base_fields_to_search
isArray: true
description: The field names of the first field to search. This can be a single
value or a comma-separated list of values. For example admin1,admin2.
- name: base_field_state
required: true
auto: PREDEFINED
predefined:
- include
- exclude
defaultValue: include
description: The state of the first field to search, meaning whether the values in
the field should be included or excluded.
- name: base_field_match
required: true
auto: PREDEFINED
predefined:
- exact
- partial
defaultValue: exact
description: Whether the values of the second field should be an exact match or a partial
match.
- name: select_fields
required: true
description: The list of fields to select within the AQL query.
defaultValue: DATEFORMAT(devicetime,'dd-MM-yyyy hh:mm'),LOGSOURCENAME(logsourceid),CATEGORYNAME(category),QIDNAME(qid),sourceip,destinationip,username
- name: time_frame
required: true
description: Time frame as used in AQL examples can be LAST 7 DAYS START '2019-09-25
15:51' STOP '2019-09-25 17:51'. For more examples, view IBM's AQL documentation.
defaultValue: LAST 1 HOURS
- name: first_additional_values
description: The values of the second field to search. This can be a single value
or a comma-separated list of values. For example admin1,admin2.
isArray: true
- name: first_additional_fields
description: The field names of the second field to search. This can be a single
value or a comma-separated list of values. For example admin1,admin2.
isArray: true
- name: first_additional_field_state
required: true
auto: PREDEFINED
predefined:
- include
- exclude
description: The state of the second field to search, meaning whether the values in
the field should be included or excluded.
defaultValue: include
- name: first_additional_field_match
required: true
auto: PREDEFINED
predefined:
- exact
- partial
description: Whether the values of the second field should be an exact match or a partial
match.
defaultValue: exact
- name: second_additional_values
description: The values of the third field to search. This can be a single value
or a comma-separated list of values. For example admin1,admin2.
- name: second_additional_fields
description: The field names of the third field to search. This can be a single
value or a comma-separated list of values. For example username,user.
- name: second_additional_field_state
required: true
auto: PREDEFINED
predefined:
- include
- exclude
description: The state of the third field to search, meaning whether the values in the
field should be included or excluded.
defaultValue: include
- name: second_additional_field_match
auto: PREDEFINED
predefined:
- exact
- partial
description: Whether the values of the third field should be an exact match or a partial
match. When choosing exact, the AQL query
will use the = operator. When choosing partial, the AQL query will use ILIKE and add '%%'
to the values.
defaultValue: exact
outputs:
- contextPath: QRadarQuery
description: The resultant AQL query based on the inputs.
type: string
subtype: python3
dockerimage: demisto/python3:3.9.8.24399
runas: DBotWeakRole
fromversion: 6.0.0
tests:
- No tests (auto formatted)
Loading

0 comments on commit d4c2f9b

Please sign in to comment.