Skip to content

Commit 67eae2d

Browse files
committed
added code for ist-ip-information
1 parent b87d7fd commit 67eae2d

File tree

2 files changed

+293
-116
lines changed

2 files changed

+293
-116
lines changed

Packs/SilentPush/Integrations/SilentPush/SilentPush.py

Lines changed: 143 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -355,7 +355,66 @@ def get_enrichment_data(self, resource: str, resource_type: str, explain: bool =
355355
raise DemistoException(f'Failed to fetch enrichment data for {resource_type} {resource}: {str(e)}')
356356

357357

358-
358+
def list_ip_information(self, ips: Union[str, List[str]], explain: bool = False, scan_data: bool = False, sparse: Optional[str] = None) -> Dict:
359+
"""
360+
Fetches information for both IPv4 and IPv6 addresses.
361+
362+
Args:
363+
ips: Either a single IP string or a list of IP strings
364+
explain: Whether to show details of data used to calculate scores
365+
scan_data: Whether to include scan data (IPv4 only)
366+
sparse: Optional specific data to return ('asn', 'asname', or 'sp_risk_score')
367+
368+
Returns:
369+
Dict: Combined results for all IP addresses
370+
"""
371+
if isinstance(ips, str):
372+
ip_list = [ip.strip() for ip in ips.split(',')]
373+
else:
374+
ip_list = ips
375+
376+
if len(ip_list) > 100:
377+
raise DemistoException("Maximum of 100 IPs can be submitted in a single request")
378+
379+
results = []
380+
381+
for ip in ip_list:
382+
try:
383+
# Determine if IPv4 or IPv6 based on presence of colons
384+
is_ipv6 = ':' in ip
385+
386+
# Build parameters
387+
params = {
388+
'explain': 1 if explain else 0
389+
}
390+
if sparse:
391+
params['sparse'] = sparse
392+
if not is_ipv6 and scan_data:
393+
params['scan_data'] = 1
394+
395+
url_suffix = f"explore/{'ipv6' if is_ipv6 else 'ipv4'}/ipv{6 if is_ipv6 else 4}info/{ip}"
396+
397+
response = self._http_request(
398+
method='GET',
399+
url_suffix=url_suffix,
400+
params=params
401+
)
402+
403+
ip_info = response.get('response', {}).get('ip2asn', [{}])[0]
404+
405+
ip_info['ip_type'] = 'ipv6' if is_ipv6 else 'ipv4'
406+
407+
results.append(ip_info)
408+
409+
except Exception as e:
410+
demisto.error(f"Error fetching information for IP {ip}: {str(e)}")
411+
results.append({
412+
'ip': ip,
413+
'ip_type': 'ipv6' if ':' in ip else 'ipv4',
414+
'error': str(e)
415+
})
416+
417+
return {'ips': results}
359418

360419

361420

@@ -652,6 +711,87 @@ def get_enrichment_data_command(client: Client, args: Dict[str, Any]) -> Command
652711
except Exception as e:
653712
demisto.error(f'Failed to get enrichment data: {str(e)}')
654713
raise
714+
715+
716+
def list_ip_information_command(client: Client, args: Dict[str, Any]) -> CommandResults:
717+
"""
718+
Command handler for fetching IP information.
719+
720+
Args:
721+
client (Client): The client instance to fetch the data
722+
args (dict): Command arguments including:
723+
- ips (str): Comma-separated list of IP addresses
724+
- explain (bool): Whether to show calculation details
725+
- scan_data (bool): Whether to include scan data (IPv4 only)
726+
- sparse (str): Optional specific data to return
727+
728+
Returns:
729+
CommandResults: XSOAR command results
730+
"""
731+
732+
ips = args.get('ips')
733+
if not ips:
734+
raise DemistoException('No IPs provided. Please provide IPs using the "ips" argument.')
735+
736+
explain = argToBoolean(args.get('explain', False))
737+
scan_data = argToBoolean(args.get('scan_data', False))
738+
sparse = args.get('sparse')
739+
740+
if sparse and sparse not in ['asn', 'asname', 'sp_risk_score']:
741+
raise DemistoException('Invalid sparse value. Must be one of: asn, asname, sp_risk_score')
742+
743+
try:
744+
745+
raw_response = client.list_ip_information(ips, explain, scan_data, sparse)
746+
ip_data = raw_response.get('ips', [])
747+
748+
markdown = ['### IP Information Results\n']
749+
750+
for ip_info in ip_data:
751+
if 'error' in ip_info:
752+
markdown.append(f"#### IP: {ip_info.get('ip', 'N/A')} (Error)\n")
753+
markdown.append(f"Error: {ip_info['error']}\n")
754+
continue
755+
756+
markdown.append(f"#### IP: {ip_info.get('ip', 'N/A')} ({ip_info.get('ip_type', 'unknown').upper()})")
757+
758+
basic_info = {
759+
'ASN': ip_info.get('asn', 'N/A'),
760+
'AS Name': ip_info.get('asname', 'N/A'),
761+
'Risk Score': ip_info.get('sp_risk_score', 'N/A'),
762+
'Subnet': ip_info.get('subnet', 'N/A')
763+
}
764+
markdown.append(tableToMarkdown('Basic Information', [basic_info], headers=basic_info.keys()))
765+
766+
if location_info := ip_info.get('ip_location', {}):
767+
location_data = {
768+
'Country': location_info.get('country_name', 'N/A'),
769+
'Continent': location_info.get('continent_name', 'N/A'),
770+
'EU Member': 'Yes' if location_info.get('country_is_in_european_union') else 'No'
771+
}
772+
markdown.append(tableToMarkdown('Location Information', [location_data], headers=location_data.keys()))
773+
774+
if ip_info.get('ip_type') == 'ipv4':
775+
additional_info = {
776+
'PTR Record': ip_info.get('ip_ptr', 'N/A'),
777+
'Is TOR Exit Node': 'Yes' if ip_info.get('ip_is_tor_exit_node') else 'No',
778+
'Is DSL/Dynamic': 'Yes' if ip_info.get('ip_is_dsl_dynamic') else 'No'
779+
}
780+
markdown.append(tableToMarkdown('Additional Information', [additional_info], headers=additional_info.keys()))
781+
782+
markdown.append('\n')
783+
784+
return CommandResults(
785+
outputs_prefix='SilentPush.IP',
786+
outputs_key_field='ip',
787+
outputs=ip_data,
788+
readable_output='\n'.join(markdown),
789+
raw_response=raw_response
790+
)
791+
792+
except Exception as e:
793+
demisto.error(f"Error in list_ip_information_command: {str(e)}")
794+
raise
655795

656796
''' MAIN FUNCTION '''
657797

@@ -694,7 +834,8 @@ def main():
694834
'silentpush-get-domain-certificates': get_domain_certificates_command,
695835
'silentpush-search-domains': search_domains_command,
696836
'silentpush-list-domain-infratags': list_domain_infratags_command,
697-
'silentpush-get-enrichment-data' : get_enrichment_data_command
837+
'silentpush-get-enrichment-data' : get_enrichment_data_command,
838+
'silentpush-list-ip-information' : list_ip_information_command
698839
}
699840

700841
if command in command_handlers:

0 commit comments

Comments
 (0)