Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

fix the ListUsedDockerImages to fine tune the output result. #15193

Merged
merged 6 commits into from
Oct 8, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Packs/CommonScripts/ReleaseNotes/1_4_42.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@

#### Scripts
##### ListUsedDockerImages
- Improve the out for the ListUsedDockerImages
149 changes: 111 additions & 38 deletions Packs/CommonScripts/Scripts/ListUsedDockerImages/ListUsedDockerImages.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,51 +32,118 @@
SCRIPT_ID = 'id'
SCRIPTS = 'scripts'

ENABLED = 'enabled'
DEPRECATED = 'deprecated'
IS_INTEGRATION_SCRIPT = 'isIntegrationScript'

MAX_PER_DOCKER = 5

''' STANDALONE FUNCTION '''
''' HELPER FUNCTION '''


def get_docker_from_conf(conf: Any) -> str:
"""
:type conf: ``json object``
:param conf: json represents integration configuration

Returns:
docker image if it is in used
"""

docker_image = ''
if INTEGRATION_SCRIPT in conf[INTEGRATION_SCRIPT] and conf[INTEGRATION_SCRIPT][SCRIPT_TYPE] in (
PYTHON_SCRIPT, POWERSHELL_SCRIPT):
if DOCKER_IMAGE not in conf[INTEGRATION_SCRIPT] or conf[INTEGRATION_SCRIPT][DOCKER_IMAGE] in (None, ''):
docker_image = 'Default Image Name'
else:
docker_image = conf[INTEGRATION_SCRIPT][DOCKER_IMAGE]
return docker_image


def get_integration_conf(integration_search_json: Any, instance_brand: str,
ignore_deprecated: bool = False) -> Any:
""" returns the corresponding integration_configuration json object for the given instance_brand
Args:
:type integration_search_json: ``json object``
:param integration_search_json: json object represents XSOAR integrations configuration.

:type instance_brand: ``str``
:param instance_brand: the configured instance brand value.

:type ignore_deprecated: ``bool``
:param ignore_deprecated: a boolean indicates if to ignore deprecated integration

Returns:
json object for the corresponding
"""

for conf in integration_search_json[CONFIGURATIONS]:
if 'id' in conf and conf['id'] != instance_brand:
continue
if ignore_deprecated and (DEPRECATED in conf) and conf[DEPRECATED] is True:
continue
if (INTEGRATION_SCRIPT not in conf) or (conf[INTEGRATION_SCRIPT] is None):
continue
else:
return conf


def extract_dockers_from_integration_search_result(content: str) -> dict:
def extract_dockers_from_integration_search_result(content: str, ignore_deprecated_integrations: bool = False,
ignore_disabled_integrations: bool = True) -> dict:
"""Returns a simple python dict of used dockerImages by integration
Args:

:type content: ``str``
:param content: string representation for the /settings/integrations/search API result response
:type content: ``str``
:param content: string representation for the /settings/integrations/search API result response

:return: dict as {"integration_id":"dockername"}
:rtype: ``dict``
:type ignore_deprecated_integrations: ``bool``
:param ignore_deprecated_integrations: a boolean indicates if to ignore deprecated integration

:type ignore_disabled_integrations: ``bool``
:param ignore_disabled_integrations: a boolean indicates if to ignore integration instances that are disabled
Returns:
:rtype: ``dict``
:return: dict as {"integration_id":"dockername"}
"""
json_content = json.loads(content)

integration_search_json = json.loads(content)
dockers = {}
for conf in json_content[CONFIGURATIONS]:
if (INTEGRATION_SCRIPT not in conf) or (conf[INTEGRATION_SCRIPT] is None):
for instance in integration_search_json['instances']:
if ignore_disabled_integrations and (ENABLED in instance and instance[ENABLED] == "false"):
continue
if IS_INTEGRATION_SCRIPT in instance and instance[IS_INTEGRATION_SCRIPT] is False:
continue
instance_brand = instance['brand']
if instance_brand == '':
continue
else:
if INTEGRATION_SCRIPT_TYPE in conf[INTEGRATION_SCRIPT] and conf[INTEGRATION_SCRIPT][SCRIPT_TYPE] in (
PYTHON_SCRIPT, POWERSHELL_SCRIPT):
if DOCKER_IMAGE not in conf[INTEGRATION_SCRIPT] or conf[INTEGRATION_SCRIPT][DOCKER_IMAGE] in (None, ''):
docker_image = 'Default Image Name'
else:
docker_image = conf[INTEGRATION_SCRIPT][DOCKER_IMAGE]
dockers[conf[INTEGRATION_DISPLAY]] = docker_image
conf_json = get_integration_conf(integration_search_json, instance_brand, ignore_deprecated_integrations)
if conf_json:
docker_image = get_docker_from_conf(conf_json)
dockers[conf_json[INTEGRATION_DISPLAY]] = docker_image

return dockers


def extract_dockers_from_automation_search_result(content: str) -> dict:
def extract_dockers_from_automation_search_result(content: str, ignore_deprecated: bool = True) -> dict:
"""Returns a simple python dict of used dockerImages by automations
Args:
:type content: ``str``
:param content: string representation for the /automation/search API result response

:type content: ``str``
:param content: string representation for the /automation/search API result response

:return: dict as {"integration_id":"dockername"}
:rtype: dict
:type ignore_deprecated: ``bool``
:param ignore_deprecated: string representation for the /automation/search API result response

Returns:
:return: dict as {"integration_id":"dockername"}
:rtype: dict
"""
json_content = json.loads(content)
dockers = {}
for script in json_content[SCRIPTS]:
if (SCRIPT_TYPE not in script) or \
if (DEPRECATED in script and script[DEPRECATED] is True) or \
(ENABLED in script and script[ENABLED] is False) or \
(SCRIPT_TYPE not in script) or \
((script[SCRIPT_TYPE] != PYTHON_SCRIPT) and (script[SCRIPT_TYPE] != POWERSHELL_SCRIPT)):
continue
else:
Expand All @@ -92,20 +159,22 @@ def extract_dockers_from_automation_search_result(content: str) -> dict:
def merge_result(docker_list: dict, result_dict: dict = {}, max_entries_per_docker: int = 5) -> dict:
"""Returns a python dict of the merge result

:type docker_list: ``dict``
:param docker_list: dictionary representation for the docker image used by integration or script
Args:
:type docker_list: ``dict``
:param docker_list: dictionary representation for the docker image used by integration or script

:type result_dict: ``dict``
:param result_dict: dictionary representation for the docker image and the integration/scripts belongs to it
merge the current result to it
:type result_dict: ``dict``
:param result_dict: dictionary representation for the docker image and the integration/scripts belongs to it
merge the current result to it

:type max_entries_per_docker: ``int``
:param max_entries_per_docker: max number of integration or script to show per docker image entry

:return: dict as {'docker_image':['integration/scripts', 'integration/scripts',...]}
:rtype: dict
:type max_entries_per_docker: ``int``
:param max_entries_per_docker: max number of integration or script to show per docker image entry

Returns:
:return: dict as {'docker_image':['integration/scripts', 'integration/scripts',...]}
:rtype: dict
"""

result = result_dict or {}
for integration_script, docker_image in docker_list.items():
if integration_script in ['CommonServerUserPowerShell', 'CommonServerUserPython']:
Expand All @@ -132,11 +201,16 @@ def format_result_for_markdown(result_dict: dict) -> list:
''' COMMAND FUNCTION '''


def list_used_docker_images(export_to_context: bool = True) -> CommandResults:
def list_used_docker_images() -> CommandResults:
md = None
active_docker_list_integration = {}
active_docker_list_automation = {}

export_to_context = demisto.args().get('export_to_context') == 'true'
ignore_deprecated_automations = demisto.args().get('ignore_deprecated_automations') == 'true'
ignore_deprecated_integrations = demisto.args().get('ignore_deprecated_integrations') == 'true'
ignore_disabled_integrations = demisto.args().get('ignore_disabled_integrations') == 'true'

''' Examples for output: { 'demisto/python3:3.9.7.24076' : ['ListUsedDockerImage', 'VirusTotal',...]}'''
result_dict: Dict[str, List[str]] = {}

Expand All @@ -145,14 +219,14 @@ def list_used_docker_images(export_to_context: bool = True) -> CommandResults:
demisto.debug(f'response code = {0}', active_integration_instances['statusCode'])
if active_integration_instances and active_integration_instances['statusCode'] == 200:
active_docker_list_integration = extract_dockers_from_integration_search_result(
active_integration_instances['body'])
active_integration_instances['body'], ignore_deprecated_integrations, ignore_disabled_integrations)

active_automation = demisto.internalHttpRequest(POST_COMMAND, '/automation/search',
'{\"size\":500}')
demisto.debug(f'response code = {0}', active_automation['statusCode'])
if active_automation and active_automation['statusCode'] == 200:
active_docker_list_automation = extract_dockers_from_automation_search_result(
active_automation['body'])
active_automation['body'], ignore_deprecated_automations)

result_dict = merge_result(active_docker_list_integration, result_dict, MAX_PER_DOCKER)
result_dict = merge_result(active_docker_list_automation, result_dict, MAX_PER_DOCKER)
Expand Down Expand Up @@ -181,8 +255,7 @@ def list_used_docker_images(export_to_context: bool = True) -> CommandResults:
def main():
demisto.debug("running list_used_docker_images()")
try:
export_to_context = demisto.args().get('export_to_context') == 'true'
return_results(list_used_docker_images(export_to_context))
return_results(list_used_docker_images())
except Exception as e:
return_error(f'Failed to execute ListUserDockerImages Script. Error: {str(e)}')

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,39 @@ args:
- "true"
- "false"
defaultValue: "true"
- default: false
description: 'Whether to ignore deprecated automation. Possible values: "true" and "false".'
isArray: false
name: ignore_deprecated_automations
required: false
secret: false
auto: PREDEFINED
predefined:
- "true"
- "false"
defaultValue: "true"
- default: false
description: 'Whether to ignore deprecated integration. Possible values: "true" and "false".'
isArray: false
name: ignore_deprecated_integrations
required: false
secret: false
auto: PREDEFINED
predefined:
- "true"
- "false"
defaultValue: "false"
- default: false
description: 'Whether to ignore disabled integration. Possible values: "true" and "false".'
isArray: false
name: ignore_disabled_integrations
required: false
secret: false
auto: PREDEFINED
predefined:
- "true"
- "false"
defaultValue: "true"
comment: 'List all Docker images that are in use by the installed integrations and automations.'
commonfields:
id: ListUsedDockerImages
Expand All @@ -35,4 +68,4 @@ subtype: python3
dockerimage: demisto/python3:3.9.7.24076
fromversion: 6.1.0
tests:
- ListUsedDockerImages - Test
- ListUsedDockerImages - Test
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,13 @@ def test_api_response_parsing():
automation_response = extract_dockers_from_automation_search_result(
util_get_content('test_data/automation_search_response.json'))

assert len(integration_response) == 29 or len(automation_response) == 226
assert len(integration_response) == 4 or len(automation_response) == 162

result_dict = {}
result_dict = merge_result(integration_response, result_dict, MAX_PER_DOCKER)
result_dict = merge_result(automation_response, result_dict, MAX_PER_DOCKER)

assert len(result_dict) == 88
assert len(result_dict) == 62

result_str = format_result_for_markdown(result_dict)

Expand Down
2 changes: 1 addition & 1 deletion Packs/CommonScripts/pack_metadata.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "Common Scripts",
"description": "Frequently used scripts pack.",
"support": "xsoar",
"currentVersion": "1.4.41",
"currentVersion": "1.4.42",
"author": "Cortex XSOAR",
"url": "https://www.paloaltonetworks.com/cortex",
"email": "",
Expand Down