Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

[XSUP 30870] Added full fields option for cs-actors and cs-reports commands #31271

Merged
merged 12 commits into from Dec 5, 2023
Expand Up @@ -93,16 +93,22 @@ def get_indicator(self, indicator_value: str) -> dict[str, Any]:
return self.cs_client.http_request(method='GET', url_suffix='intel/combined/indicators/v1', params=params)

def cs_actors(self, args: dict[str, str]) -> dict[str, Any]:
url_suffix = 'intel/combined/actors/v1'
if argToBoolean(args.pop('display_full_fields', False)):
url_suffix += '?fields=__full__'
params: dict[str, Any] = self.build_request_params(args)
return self.cs_client.http_request(method='GET', url_suffix='intel/combined/actors/v1', params=params)
return self.cs_client.http_request(method='GET', url_suffix=url_suffix, params=params)

def cs_indicators(self, args: dict[str, str]) -> dict[str, Any]:
params: dict[str, Any] = self.build_request_params(args)
return self.cs_client.http_request(method='GET', url_suffix='intel/combined/indicators/v1', params=params)

def cs_reports(self, args: dict[str, str]) -> dict[str, Any]:
url_suffix = 'intel/combined/reports/v1'
if argToBoolean(args.pop('display_full_fields', False)):
url_suffix += '?fields=__full__'
params: dict[str, Any] = self.build_request_params(args)
return self.cs_client.http_request(method='GET', url_suffix='intel/combined/reports/v1', params=params)
return self.cs_client.http_request(method='GET', url_suffix=url_suffix, params=params)


''' HELPER FUNCTIONS '''
Expand Down Expand Up @@ -279,6 +285,8 @@ def get_values(items_list: List[Any], return_type: str = 'str', keys: str | List
:return: The values list
"""
new_list: List[Any] = []
if not items_list:
return new_list
if isinstance(keys, str):
new_list = [item.get(keys) for item in items_list]
elif isinstance(keys, list):
Expand Down Expand Up @@ -394,6 +402,7 @@ def cs_actors_command(client: Client, args: dict[str, str]) -> CommandResults:
url = r.get('url')
slug = r.get('slug')
short_description = r.get('short_description')
description = r.get('description')
first_activity_date = r.get('first_activity_date')
last_activity_date = r.get('last_activity_date')
active = r.get('active')
Expand All @@ -414,6 +423,7 @@ def cs_actors_command(client: Client, args: dict[str, str]) -> CommandResults:
'URL': url,
'Slug': slug,
'ShortDescription': short_description,
'Description': description,
'FirstActivityDate': datetime.fromtimestamp(first_activity_date, timezone.utc).isoformat()
if first_activity_date else None,
'LastActivityDate': datetime.fromtimestamp(last_activity_date, timezone.utc).isoformat()
Expand Down Expand Up @@ -445,7 +455,7 @@ def cs_actors_command(client: Client, args: dict[str, str]) -> CommandResults:
outputs=outputs,
outputs_key_field='ID',
outputs_prefix='FalconIntel.Actor',
readable_output=md if md else tableToMarkdown(name=title, t=md_outputs, headerTransform=pascalToSpace),
readable_output=md if md else tableToMarkdown(name=title, t=md_outputs, headerTransform=pascalToSpace, removeNull=True),
raw_response=res
)

Expand Down Expand Up @@ -515,6 +525,7 @@ def cs_reports_command(client: Client, args: dict[str, str]) -> CommandResults:
created_date: int = r.get('created_date')
last_modified_date: int = r.get('last_modified_date')
short_description: str = r.get('short_description')
description: str = r.get('description')
target_industries: List[Any] = r.get('target_industries') or []
target_countries: List[Any] = r.get('target_countries') or []
motivations: List[Any] = r.get('motivations') or []
Expand All @@ -533,6 +544,7 @@ def cs_reports_command(client: Client, args: dict[str, str]) -> CommandResults:
'LastModifiedSate': datetime.fromtimestamp(last_modified_date, timezone.utc).isoformat()
if last_modified_date else None,
'ShortDescription': short_description,
'Description': description,
yaakovpraisler marked this conversation as resolved.
Show resolved Hide resolved
'TargetIndustries': get_values(target_industries, return_type='list'),
'TargetCountries': get_values(target_countries, return_type='list'),
'Motivations': get_values(motivations, return_type='list'),
Expand All @@ -555,7 +567,7 @@ def cs_reports_command(client: Client, args: dict[str, str]) -> CommandResults:
outputs_prefix='FalconIntel.Report',
outputs=outputs,
outputs_key_field='ID',
readable_output=md if md else tableToMarkdown(name=title, t=outputs, headerTransform=pascalToSpace),
readable_output=md if md else tableToMarkdown(name=title, t=outputs, headerTransform=pascalToSpace, removeNull=True),
raw_response=res
)

Expand Down
Expand Up @@ -86,7 +86,7 @@ configuration:
advanced: true
required: false
script:
dockerimage: demisto/python3:3.10.13.82076
dockerimage: demisto/python3:3.10.13.82467
type: python
subtype: python3
script: '-'
Expand Down Expand Up @@ -453,6 +453,9 @@ script:
- last_modified_date|desc
- name: slug
description: 'Search by ''slug'' or short descriptive name. For example, "anchor-panda".'
- name: display_full_fields
description: Whether to return and display full data from CS API. (For example full description, which by default is short).
defaultValue: false
outputs:
- contextPath: FalconIntel.Actor.ImageURL
description: The URL of the actor image.
Expand All @@ -472,6 +475,9 @@ script:
- contextPath: FalconIntel.Actor.ShortDescription
description: The short description of the actor.
type: String
- contextPath: FalconIntel.Actor.Description
description: The full description of the actor.
type: String
- contextPath: FalconIntel.Actor.FirstActivityDate
description: The first activity date of the actor.
type: Date
Expand Down Expand Up @@ -799,6 +805,9 @@ script:
- created_date|desc
- last_modified_date|asc
- last_modified_date|desc
- name: display_full_fields
description: Whether to display the full fields result from CS API.
defaultValue: false
outputs:
- contextPath: FalconIntel.Report.ID
description: The ID of the report.
Expand Down Expand Up @@ -827,6 +836,9 @@ script:
- contextPath: FalconIntel.Report.ShortDescription
description: The short description of the report.
type: String
- contextPath: FalconIntel.Report.Description
description: The full description of the report.
type: String
- contextPath: FalconIntel.Report.TargetIndustries
description: "Targeted industries included in the report. For example, aerospace."
type: String
Expand Down
Expand Up @@ -215,3 +215,39 @@ def test_bang_commands(mocker, indicators_type, values):

results = demisto.results.call_args[0][0]
assert len(results) == len(values.split(','))


@pytest.mark.parametrize("args, excepted", [({}, False), ({"display_full_fields": True}, True)])
def test_cs_acotrs(mocker, args, excepted):
"""
Given:
- The args object with or without the display_full_fields argument.

When:
- Running cs_actors.

Then:
- Ensure we add the fields query param in case the argument is True.
"""
mock_request = mocker.patch.object(CrowdStrikeClient, "http_request")
client = Client(params={})
client.cs_actors(args=args)
assert ("fields=__full__" in mock_request.call_args[1]["url_suffix"]) == excepted


@pytest.mark.parametrize("args, excepted", [({}, False), ({"display_full_fields": True}, True)])
def test_cs_reports(mocker, args, excepted):
"""
Given:
- The args object with or without the display_full_fields argument.

When:
- Running cs_reports.

Then:
- Ensure we add the fields query param in case the argument is True.
"""
mock_request = mocker.patch.object(CrowdStrikeClient, "http_request")
client = Client(params={})
client.cs_reports(args=args)
assert ("fields=__full__" in mock_request.call_args[1]["url_suffix"]) == excepted
Expand Up @@ -569,6 +569,7 @@ Search known actors based on the given parameters.
| limit | The maximum number of actors to retrieve. The default is 10. | Optional |
| sort | Sort by field and direction. | Optional |
| slug | Search by 'slug' or short descriptive name. Ex: "anchor-panda" | Optional |
| display_full_fields | Whether to display the full fields result from CS API. Default is False | Optional |


#### Context Output
Expand All @@ -581,6 +582,7 @@ Search known actors based on the given parameters.
| FalconIntel.Actor.URL | String | The url of the actor |
| FalconIntel.Actor.Slug | String | Slug name ofactor |
| FalconIntel.Actor.ShortDescription | String | The actor short description. |
| FalconIntel.Actor.Description | String | The actor full description. |
| FalconIntel.Actor.FirstActivityDate | Date | The actor first activity date. |
| FalconIntel.Actor.LastActivityDate | Date | The actor last activity date. |
| FalconIntel.Actor.Active | Boolean | The actor active status. |
Expand Down Expand Up @@ -617,7 +619,8 @@ Search known actors based on the given parameters.
"Eastern Europe",
"Russian Federation"
],
"ShortDescription": "TWISTED SPIDER is the criminal group behind the development and operation of Maze ransomware. While the ransomware was first observed in May 2019, the group gained notoriety in November 2019 with their brazen attitude toward victims and their willingness to speak with security researchers as they began using Big Game Hunting (BGH) tactics to target organizations and businesses. While other actors ...",
"ShortDescription": "TWISTED SPIDER is the criminal group behind the development and operation of Maze ransomware. While the ransomware was first observed in May 2019, the group gained notoriety in November 2019 with their brazen attitude toward victims and their willingness to speak with security researchers as they began using Big Game Hunting (BGH) tactics to target ...",
"Description": "TWISTED SPIDER is the criminal group behind the development and operation of Maze ransomware. While the ransomware was first observed in May 2019, the group gained notoriety in November 2019 with their brazen attitude toward victims and their willingness to speak with security researchers as they began using Big Game Hunting (BGH) tactics to target organizations and businesses.",
"Slug": "twisted-spider",
"TargetCountries": [
"Algeria",
Expand Down Expand Up @@ -900,6 +903,7 @@ The Falcon Intel Reports API allows to query CrowdStrike intelligence publicatio
| offset | Used to paginate the response. You can then use limit to set the number of results for the next page. | Optional |
| limit | The maximum number of reports to retrieve. The default is 10. | Optional |
| sort | Sort by field and direction. | Optional |
| display_full_fields | Whether to display the full fields result from CS API. Default is False | Optional |


#### Context Output
Expand All @@ -915,6 +919,7 @@ The Falcon Intel Reports API allows to query CrowdStrike intelligence publicatio
| FalconIntel.Report.CreatedDate | Date | The date the report was created. |
| FalconIntel.Report.LastModifiedSate | Date | The date the report was last modified. |
| FalconIntel.Report.ShortDescription | String | The report short description. |
| FalconIntel.Report.Description | String | The report full description. |
| FalconIntel.Report.TargetIndustries | String | Targeted industries included in the report. Ex: aerospace |
| FalconIntel.Report.TargetCountries | String | Targeted countries included in the report. Ex: afghanistan |
| FalconIntel.Report.Motivations | String | Motivations included in the report. Ex: criminal |
Expand All @@ -933,7 +938,8 @@ The Falcon Intel Reports API allows to query CrowdStrike intelligence publicatio
"ID": 7448,
"LastModifiedSate": "2020-07-24T10:15:02.000Z",
"Name": "Snort Changelog",
"ShortDescription": "Added one additional rule to detect Hancitor malware traffic decsribed in CSIT-16107. ",
"ShortDescription": "Added one additional rule to detect Hancitor ...",
"Description": "Added one additional rule to detect Hancitor malware traffic decsribed in CSIT-16107. ",
"Slug": "slug_value",
"SubType": "Snort/Suricata",
"Type": "Feeds",
Expand Down
7 changes: 7 additions & 0 deletions Packs/CrowdStrikeIntel/ReleaseNotes/2_0_35.md
@@ -0,0 +1,7 @@

#### Integrations

##### CrowdStrike Falcon Intel v2

- Added the *display_full_fields* argument to the ***cs-actors*** and the ***cs-reports*** commands.
- Updated the Docker image to: *demisto/python3:3.10.13.82467*.
2 changes: 1 addition & 1 deletion Packs/CrowdStrikeIntel/pack_metadata.json
Expand Up @@ -2,7 +2,7 @@
"name": "CrowdStrike Falcon Intel",
"description": "Threat intelligence service by CrowdStrike focused on delivering a technical feed to help organizations better defend themselves against adversary activity.",
"support": "xsoar",
"currentVersion": "2.0.34",
"currentVersion": "2.0.35",
"author": "Cortex XSOAR",
"url": "https://www.paloaltonetworks.com/cortex",
"email": "",
Expand Down