ipinfo_v2
Use the IPinfo.io API to get data about an IP address.
Data Enrichment & Threat Intelligence · Ipinfo
Details
| ID | ipinfo_v2 |
|---|---|
| Provider | IPinfo |
| Category | Data Enrichment & Threat Intelligence |
| From Version | 5.5.0 |
| Docker Image | demisto/python3:3.12.13.10116658 |
| Supported Modules | Agentix XSIAM |
README
Use the IPinfo.io API to get data about an IP address.
Differences from IPinfo (v1)
- The
ip-fieldcommand has been removed on v2: all outputs are available by runningip. - IPinfo v2 Allows setting source reliability.
- IPinfo v2 Enriches data with IP-hostname relationships.
Configure IPinfo v2 in Cortex
| Parameter | Description | Required |
|---|---|---|
| API Token | The API key to use for the connection. | False |
| Source Reliability | Reliability of the source providing the intelligence data. | True |
| Base URL | True | |
| Trust any certificate (not secure) | False | |
| Use system proxy settings | False |
Commands
You can execute these commands from the CLI, as part of an automation, or in a playbook.
After you successfully execute a command, a DBot message appears in the War Room with the command details.
ip
Check IP reputation (when information is available, returns a JSON with details). Uses all configured Threat Intelligence feeds.
Base Command
ip
Input
| Argument Name | Description | Required |
|---|---|---|
| ip | IP address to query, e.g., 1.1.1.1. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| IPinfo.IP.Address | String | The IP address. |
| IPinfo.IP.Hostname | String | The IP hostname. |
| IPinfo.IP.ASN | String | The IP ASN. |
| IPinfo.IP.ASOwner | String | The IP AS owner. |
| IPinfo.IP.Organization.Name | String | The IP organization name (Only available in some IPinfo.io plans). |
| IPinfo.IP.Organization.Type | String | The IP organization type (Only available in some IPinfo.io plans). |
| IPinfo.IP.Geo.Location | String | The IP geographic location (coordinates as lat:lon). |
| IPinfo.IP.Geo.Country | String | The IP country. |
| IPinfo.IP.Geo.Description | String | The IP location as <City, Region, Postal Code, Country>. |
| IPinfo.IP.Registrar.Abuse.Address | String | The physical address registered for receiving abuse reports for the IP. (Only available in some IPinfo.io plans). |
| IPinfo.IP.Registrar.Abuse.Country | String | The country where abuse reports are received for the IP. (Only available in some IPinfo.io plans). |
| IPinfo.IP.Registrar.Abuse.Email | String | The email address for abuse reports provided by the IP. (Only available in some IPinfo.io plans). |
| IPinfo.IP.Registrar.Abuse.Name | String | The name of the abuse report handler received for the IP. (Only available in some IPinfo.io plans). |
| IPinfo.IP.Registrar.Abuse.Network | String | The IP range relevant for abuse inquiries provided for the IP. (Only available in some IPinfo.io plans). |
| IP.Address | String | The IP address. |
| IP.Hostname | String | The IP hostname. |
| IP.ASN | String | The IP ASN. |
| IP.Tags | String | Tags related the IP use (hosting, proxy, tor, vpn). |
| IP.FeedRelatedIndicators.value | String | Names of indicators associated with the IP. |
| IP.FeedRelatedIndicators.type | String | Types of indicators associated with the IP. |
| IP.Relationships.EntityA | string | The source of the relationship. |
| IP.Relationships.EntityB | string | The destination of the relationship. |
| IP.Relationships.Relationship | string | The name of the relationship. |
| IP.Relationships.EntityAType | string | The type of the source of the relationship. |
| IP.Relationships.EntityBType | string | The type of the destination of the relationship. |
| IP.Geo.Location | String | The IP geographic location (coordinates as lat:lon) |
| IP.Geo.Country | String | The IP country. |
| IP.Geo.Description | String | The IP location as <City, Region, Postal Code, Country>. |
| IP.Organization.Name | String | The organization of the IP. |
| IP.Organization.Type | String | The organization type of the IP. |
| DBotScore.Indicator | String | The indicator that was tested. |
| DBotScore.Score | Number | The actual score. |
| DBotScore.Reliability | String | How reliable the score is (for example, “C - fairly reliable”). |
| DBotScore.Type | String | The indicator type. |
| DBotScore.Vendor | String | The vendor used to calculate the score. |
Command example
!ip ip=1.1.1.1
Context Example
{
"DBotScore": {
"Indicator": "1.1.1.1",
"Reliability": "C - Fairly reliable",
"Score": 0,
"Type": "ip",
"Vendor": "ipinfo_v2"
},
"IP": {
"ASN": "AS13335",
"Address": "1.1.1.1",
"FeedRelatedIndicators": [
{
"description": "Hostname",
"type": "URL",
"value": "one.one.one.one"
},
{
"description": "AS domain",
"type": "Domain",
"value": "cloudflare.com"
},
{
"description": "Company domain",
"type": "Domain",
"value": "cloudflare.com"
}
],
"Geo": {
"Country": "US",
"Description": "Los Angeles, California, 90076, US",
"Location": "34.0522:-118.2437"
},
"Hostname": "one.one.one.one",
"Organization": {
"Name": "APNIC and Cloudflare DNS Resolver project",
"Type": "hosting"
},
"Relationships": [
{
"EntityA": "1.1.1.1",
"EntityAType": "IP",
"EntityB": "one.one.one.one",
"EntityBType": "Domain",
"Relationship": "resolves-to"
}
],
"Tags": "hosting"
},
"IPinfo": {
"IP": {
"ASN": "AS13335",
"ASOwner": "Cloudflare, Inc.",
"Address": "1.1.1.1",
"Geo": {
"Country": "US",
"Description": "Los Angeles, California, 90076, US",
"Location": "34.0522,-118.2437"
},
"Hostname": "one.one.one.one",
"Organization": {
"Name": "APNIC and Cloudflare DNS Resolver project",
"Type": "hosting"
},
"Registrar": {
"Abuse": {
"Address": "PO Box 3646, South Brisbane, QLD 4101, Australia",
"Country": "AU",
"Email": "test",
"Name": "APNIC RESEARCH",
"Network": "1.1.1.0/24",
"Phone": "+61-7-3858-3188"
}
},
"Tags": [
"hosting"
]
}
}
}
Human Readable Output
IPinfo results for 1.1.1.1
| anycast | city | country | hostname | ip | loc | org | postal | readme | region | timezone |
|---|---|---|---|---|---|---|---|---|---|---|
| true | Miami | US | one.one.one.one | 1.1.1.1 | 25.7867,-80.1800 | AS13335 Cloudflare, Inc. | 33132 | https |
Configuration parameters
credentials—integrationReliability— Source Reliability (required)base_url— Base URL (required)insecure— Trust any certificate (not secure)proxy— Use system proxy settings
Commands (1)
-
ipCheck IP reputation (when information is available, returns a JSON with details). Uses all configured Threat Intelligence feeds.
from CommonServerPython import * # noqa # pylint: disable=unused-wildcard-import from CommonServerUserPython import * # noqa import traceback from typing import Any BRAND_NAME = "IPinfo" # matches context output path for faster caching class Client(BaseClient): def __init__(self, api_key: str, base_url: str, verify_certificate: bool, proxy: bool, reliability: str): """ Client to use in the IPinfo integration. Uses BaseClient """ super().__init__(base_url=base_url, proxy=proxy, verify=verify_certificate) time_sensitive = is_time_sensitive() demisto.debug(f"{time_sensitive=}") self.timeout = 2 if time_sensitive else 20 self.api_key = api_key self.reliability = reliability def ipinfo_ip(self, ip: str) -> dict[str, Any]: return self.http_request(ip) def http_request(self, ip: str) -> dict[str, Any]: """constructs url with token (if existent), then returns request""" return self._http_request( method="GET", url_suffix=f"{ip}/json", params=assign_params(token=self.api_key), timeout=self.timeout ) def test_module(client: Client) -> str: """Tests IPinfo by sending a query on 8.8.8.8""" client.ipinfo_ip("8.8.8.8") return "ok" # on any failure, an exception is raised def ipinfo_ip_command(client: Client, ip: str) -> List[List[CommandResults]]: ip_lists = argToList(ip) ip_results = [] for ip in ip_lists: response = client.ipinfo_ip(ip) ip_results.append(parse_results(ip, response, client.reliability)) return ip_results def parse_results(ip: str, raw_result: dict[str, Any], reliability: str) -> List[CommandResults]: command_results: List[CommandResults] = [] # default values asn = as_owner = None feed_related_indicators: List[Common.FeedRelatedIndicators] = [] relationships: list[EntityRelationship] = [] if not raw_result: return command_results hostname = str(raw_result.get("hostname", "")) hostname_indicator_type = FeedIndicatorType.URL if urlRegex.find(hostname) else FeedIndicatorType.Domain feed_related_indicators.append(Common.FeedRelatedIndicators(hostname, hostname_indicator_type, "Hostname")) relationships.append( EntityRelationship( name=EntityRelationship.Relationships.RESOLVES_TO, entity_a=ip, entity_a_type=FeedIndicatorType.IP, entity_b=hostname, entity_b_type=FeedIndicatorType.Domain, brand=BRAND_NAME, source_reliability=reliability, ) ) if "org" in raw_result: org = raw_result.get("org", "") if " " in org: org_parts = org.split(" ") asn, as_owner = org_parts[0], " ".join(org_parts[1:]) # example of a field only available on paid accounts if "asn" in raw_result: asn = demisto.get(raw_result, "asn.asn") as_owner = demisto.get(raw_result, "asn.name") as_domain = demisto.get(raw_result, "asn.domain") if as_domain: feed_related_indicators.append(Common.FeedRelatedIndicators(as_domain, FeedIndicatorType.Domain, "AS domain")) organization = ( {"Name": demisto.get(raw_result, "company.name"), "Type": demisto.get(raw_result, "company.type")} if "company" in raw_result else None ) company_domain = demisto.get(raw_result, "company.domain") if company_domain is not None: feed_related_indicators.append(Common.FeedRelatedIndicators(company_domain, FeedIndicatorType.Domain, "Company domain")) abuse = ( { "Address": demisto.get(raw_result, "abuse.address"), "Country": demisto.get(raw_result, "abuse.country"), "Name": demisto.get(raw_result, "abuse.name"), "Network": demisto.get(raw_result, "abuse.network"), "Phone": demisto.get(raw_result, "abuse.phone"), "Email": demisto.get(raw_result, "abuse.email"), } if "abuse" in raw_result else None ) tags = [] for tag_path, tag_name in ( ("privacy.hosting", "hosting"), ("privacy.proxy", "proxy"), ("privacy.tor", "tor"), ("privacy.vpn", "vpn"), ): if demisto.get(raw_result, tag_path): tags.append(tag_name) city = raw_result.get("city", "") region = raw_result.get("region", "") postal = raw_result.get("postal", "") country = raw_result.get("country", "") description = ", ".join(filter(None, [city, region, postal, country])) # parses geolocation lat = lon = None loc = raw_result.get("loc", "") # empty string as default on purpose, if "," in loc: coordinates = loc.split(",") lat, lon = float(coordinates[0]), float(coordinates[1]) entry_context = { "Address": raw_result.get("ip"), "Hostname": hostname, # type: ignore "ASN": asn, "ASOwner": as_owner, "Tags": tags, # type: ignore "Organization": organization, "Geo": {"Location": loc, "Country": country, "Description": description}, # type: ignore "Registrar": {"Abuse": abuse} if abuse else None, } outputs_key_field = "Address" # marks the ip address if DBotScoreReliability.is_valid_type(reliability): dbot_reliability = DBotScoreReliability.get_dbot_score_reliability_from_str(reliability) else: raise Exception("Please provide a valid value for the Source Reliability parameter.") indicator = Common.IP( ip=ip, dbot_score=Common.DBotScore( indicator=ip, indicator_type=DBotScoreType.IP, reliability=dbot_reliability, integration_name=BRAND_NAME, score=Common.DBotScore.NONE, ), asn=asn, hostname=hostname, feed_related_indicators=feed_related_indicators, geo_latitude=str(lat) if lat else None, geo_longitude=str(lon) if lon else None, geo_description=description or None, geo_country=country, tags=",".join(tags), organization_name=organization.get("Name") if organization else None, organization_type=organization.get("Type") if organization else None, relationships=relationships, ) if lat and lon: raw_result.update({"lat": lat, "lng": lon}) map_output = CommandResults( raw_response={"lat": lat, "lng": lon}, entry_type=EntryType.MAP_ENTRY_TYPE, outputs_key_field=outputs_key_field, indicator=indicator, ) command_results.append(map_output) # do not change the order of the calls for CommandResults due to an issue where the ip command would not # present all of the information returned from the API. command_results.append( CommandResults( readable_output=tableToMarkdown(f"IPinfo results for {ip}", raw_result), raw_response=raw_result, outputs_prefix="IPinfo.IP", outputs=entry_context, outputs_key_field=outputs_key_field, indicator=indicator, relationships=relationships, ) ) return command_results def main() -> None: """main function, parses params and runs command functions""" params = demisto.params() args = demisto.args() command = demisto.command() proxy = params.get("proxy") or False api_key = demisto.get(params, "credentials.password") or "" insecure = params.get("insecure") or False base_url = params.get("base_url") or "https://ipinfo.io" reliability = params.get("integrationReliability") demisto.debug(f"Command being called is {command}") try: client = Client(api_key=api_key, verify_certificate=not insecure, proxy=proxy, base_url=base_url, reliability=reliability) if command == "test-module": return_results(test_module(client)) elif command == "ip": ip_command = ipinfo_ip_command(client, **args) return_results(ip_command) else: raise NotImplementedError(f"command {command} is not supported") # Log exceptions and return errors except Exception as e: demisto.error(traceback.format_exc()) # print the traceback return_error(f"Failed to execute {command} command.\nError:\n{e!s}") if __name__ in ("__main__", "__builtin__", "builtins"): main()