# IPinfo

## Overview

Panther has partnered with [IPinfo](https://ipinfo.io/), a trusted source for IP address data, to provide integrated IP related enrichment to Panther customers.

Use IPinfo enrichment data in your Panther detections to reduce false-positive alerts by:

* Cross-examining the current IP geolocation details of suspicious users to discover irregularities in profile information and blocking them.
* Preemptively identifying and blocking traffic from high-risk locations or networks before they make it to you.
* Accurately and reliably discovering other entities related to the target that may pose a security risk.

The IPinfo data sets are available to all Panther accounts at no additional cost and are disabled by default. Learn how to [view stored enrichment data here](https://docs.panther.com/enrichment/..#viewing-and-managing-enrichments), and how to [view log events with enrichment data here](https://docs.panther.com/enrichment/..#viewing-log-events-with-enrichment-data).

### How IPinfo works

Alert events are automatically enriched with IPinfo data within the `p_enrichment` field in JSON events.

IPinfo data can be accessed in detections with [pre-built Python helpers](#available-methods) (and [`deep_get`](https://docs.panther.com/detections/rules/python/globals#deep_get)).

[IPinfo datasets](#ipinfo-datasets) are stored as enrichment tables in bulk, so there is no need to make API calls to leverage this enrichment in your detection logic or alerts.

The data from IPinfo is updated once a day.

### IPinfo datasets

There are three data types available from IPinfo that add contextual information about IP addresses:

* [Geolocation Data](https://ipinfo.io/developers/data-types#geolocation-data)
* [ASN Data](https://ipinfo.io/developers/data-types#asn-data)
* [Privacy Data](https://ipinfo.io/developers/data-types#privacy-data)

## How to enable IPinfo datasets

If you are using a CI/CD workflow, please see [the CI/CD Users section below](#ci-cd-users) to learn about additional considerations.

{% hint style="info" %}
To enable Analyst roles to view and manage IPinfo packages in the Panther Console, they will need to be assigned the **View Lookups** and **Manage Lookups** permissions.
{% endhint %}

To enable IPinfo enrichments:

1. In the left-hand navigation bar of your Panther Console, click **Detections.**
2. Click the **Packs** tab.
   * On this page, you can see built-in packs available for IPinfo.
3. On the right side of the IPInfo tile you wish to enable, click the toggle to enable the pack.
4. Click **Continue** in the dialog that appears.

   <figure><img src="https://4011785613-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LgdiSWdyJcXPahGi9Rs-2910905616%2Fuploads%2Fgit-blob-c253b0518a7638066e78fabcfd0c4d436d7d8709%2Fenable-detection-pack.png?alt=media" alt=""><figcaption></figcaption></figure>

   * If you'd like to make additional changes through CI/CD with the [Panther Analysis Tool (PAT)](https://docs.panther.com/panther-developer-workflows/detections-repo/pat), please contact your Panther representative for more information.
5. To verify if the IPinfo data sets are enabled, from the left sidebar menu, click **Configure** > **Enrichment Providers.**
   * On this page, you can see all enrichment sources, whether each source is currently enabled or disabled, and when a source’s data was last refreshed.
   * The six IPinfo source tables are visible, as well as the time they were last refreshed. Disabled data sets will not be refreshed.

     * The `ipinfo_asn` ,`ipinfo_location` and `ipinfo_privacy` tables are used for real-time lookups in the detection engine.
     * The `ipinfo_asn_datalake` , `ipinfo_location_datalake` and `ipinfo_privacy_datalake` tables are used for querying and joining to IPinfo data in the datalake.

     <figure><img src="https://4011785613-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LgdiSWdyJcXPahGi9Rs-2910905616%2Fuploads%2Fgit-blob-949da00adf04dbe323a38ce3379566036282c776%2Fimage%20(3)%20(1)%20(2)%20(1)%20(1)%20(1)%20(1)%20(1)%20(1).png?alt=media" alt=""><figcaption></figcaption></figure>

### CI/CD users

To enable IPinfo enrichment in the CLI workflow, see the [Managing Enrichments with the Panther Analysis Tool](https://docs.panther.com/panther-developer-workflows/detections-repo/pat/managing-enrichment) guide.

Please note the following considerations:

* CI/CD users do not need to use Detection Packs to get IPinfo tables. You can pull in the latest release of [`panther-analysis`](https://github.com/panther-labs/panther-analysis) and use the `panther_analysis_tool` (PAT) to upload the IPinfo enrichments.
  * To enable the IPinfo tables using the [`panther-analysis`](https://github.com/panther-labs/panther-analysis) repository, make sure to open each corresponding YAML configuration file and set `enabled: true`.
* It is possible for CI/CD users to enable IPinfo enrichments via Detection Packs, as long as you do not customize the IPinfo tables using PAT.
  * If you choose to manage IPinfo through PAT after enabling it in the Panther Console, you must first disable the Detection Packs in the Panther Console. Simultaneous use of both the Panther Console and PAT to manage IPinfo is not supported.
* For more information on how to manage IPinfo enrichment, please see the [IPinfo files in Panther's GitHub repository](https://github.com/panther-labs/panther-analysis/tree/master/lookup_tables/ipinfo).

## How to query IPinfo data in the data lake

There are three IPinfo tables in the data lake:

* `ipinfo_asn_datalake`
  * See [IPinfo's ASN API documentation](https://ipinfo.io/products/asn-api).
* `ipinfo_location_datalake`
  * See [IPinfo's IP Geolocation API documentation](https://ipinfo.io/products/ip-geolocation-api).
* `ipinfo_privacy_datalake`
  * See [IPinfo's Privacy Detection API documentation](https://ipinfo.io/products/proxy-vpn-detection-api).

For each of the above tables, there is also a `<table>_history` table that records all changes.

### Using a `joinkey`

When querying the data lake for IPinfo data, you must use a `joinkey` to make the queries efficient. The following user-defined functions make setting a `joinkey` easier:

* `PANTHER_LOOKUPS.PUBLIC.IPINFO_RANGE_TO_CIDR`
* `PANTHER_LOOKUPS.PUBLIC.IPINFO_TO_INT`
* `PANTHER_LOOKUPS.PUBLIC.IPINFO_TO_IP`
  * Note: IPinfo's code for `TO_IP` supports IPv4 only.
* `PANTHER_LOOKUPS.PUBLIC.IPINFO_TO_JOIN_KEY`

See an [example showing how to query the data lake using a `joinkey` below](#example-query-the-data-lake-for-ipinfo-data-using-a-joinkey).

## Examples

### Example: Alert based on IPinfo location data

In this example, we create a rule that emits an alert on every login to the AWS console that is done from an unexpected country.

```python
def rule(event):
    global ipinfo_location
    ipinfo_location = IPInfoLocation(event)
    match_field = ""
    if event.get("p_log_type") == "AWS.Cloudtrail":
        match_field = "sourceIPAddress"
    
    if event.get("eventname") == 'ConsoleLogin' and ipinfo_location.country(match_field) != "US":
        return True
    return False
```

### Example: Query the data lake for IPinfo data using a `joinkey`

To look up the IP `71.114.47.25`, you will need to specify a `joinkey` and range.

```sql
SELECT
   *
FROM
   panther_lookups.public.ipinfo_asn_datalake
WHERE 
   PANTHER_LOOKUPS.PUBLIC.IPINFO_TO_JOIN_KEY(joinkey) = PANTHER_LOOKUPS.PUBLIC.IPINFO_TO_JOIN_KEY('71.114.47.25')
   AND 
   PANTHER_LOOKUPS.PUBLIC.IPINFO_TO_INT('71.114.47.25') BETWEEN 
     PANTHER_LOOKUPS.PUBLIC.IPINFO_TO_INT(startip) 
       AND PANTHER_LOOKUPS.PUBLIC.IPINFO_TO_INT(endip)

```

To join to another table, follow the same pattern as above, but use the IP address in the log table.

```sql
SELECT
   log.*, 
   ipinfo.* EXCLUDE (p_schema_version,p_event_time, p_parse_time,p_log_type,p_row_id,p_source_id,p_source_label)
FROM
   panther_logs.public.panther_audit log 
     LEFT OUTER JOIN panther_lookups.public.ipinfo_asn_datalake ipinfo
   ON (
     PANTHER_LOOKUPS.PUBLIC.IPINFO_TO_JOIN_KEY(joinkey) = PANTHER_LOOKUPS.PUBLIC.IPINFO_TO_JOIN_KEY(log.sourceIP)
     AND 
     PANTHER_LOOKUPS.PUBLIC.IPINFO_TO_INT(log.sourceIP) BETWEEN 
       PANTHER_LOOKUPS.PUBLIC.IPINFO_TO_INT(startip) AND PANTHER_LOOKUPS.PUBLIC.IPINFO_TO_INT(endip)
   )
WHERE
   p_occurs_since('1 day', log)
LIMIT 10
```

## IPinfo Python helper function usage and methods

Panther has integrated helper functions to streamline the use of IPInfo data in the real-time detection engine.

### Creating IPinfo objects in a Python rule

There are helper functions that create objects with methods that can be called to return relevant data from the dataset.

Below is an example code snippet that shows the creation of these objects:

{% code overflow="wrap" %}

```python
from panther_ipinfo_helpers import (IPInfoASN, IPInfoLocation, geoinfo_from_ip)

def rule(event):
    global ipinfo_location
    global ipinfo_asn
    ipinfo_location = IPInfoLocation(event) 
    ipinfo_asn = IPInfoASN(event)
```

{% endcode %}

The `global` keyword is only needed if you intend to use the objects outside of the function in which they are declared.

### Calling methods on the IPinfo objects

The various components of the IPinfo datasets are available via methods on the `_location` and `_asn` objects. It's possible for one event that your rule is processing to have multiple fields (such as IP addresses, source, and destination IP in a network log). When calling the IPInfo objects, make sure to specify which field you are looking for.

The example below demonstrates calling all helper methods on the `ipinfo_location` and `ipinfo_asn` objects we created in the previous example, to get all the enrichment information available in the detection's rule.

```python
    match_field = ""
    if event.get("p_log_type") == "AWS.Cloudtrail":
        match_field = "sourceIPAddress"
    
    if ipinfo_location:
        city = ipinfo_location.city(match_field)
        country = ipinfo_location.country(match_field)
        latitude = ipinfo_location.latitude(match_field)
        longitude = ipinfo_location.longitude(match_field)
        postal_code = ipinfo_location.postal_code(match_field)
        region = ipinfo_location.region(match_field)
        region_code = ipinfo_location.region_code(match_field)
        timezone = ipinfo_location.timezone(match_field)
    
    if ipinfo_asn:
        asn = ipinfo_asn.asn(match_field)
        domain = ipinfo_asn.domain(match_field)
        name = ipinfo_asn.name(match_field)
        route = ipinfo_asn.route(match_field)
        asn_type = ipinfo_asn._type(match_field)
```

The next example uses the `geoinfo_from_ip()` function that returns a dictionary with geolocation information in the same format as `panther_oss_helper.geoinfo_from_ip()`, except it does not provide `hostname` and `anycast` fields.

```python
result = geoinfo_from_ip(event, "sourceIPAddress")
```

If the event field being referenced is an array, then the helper function will return an array of the matching values. For example:

```python
countries_of_all_ips = ipinfo_location.country('p_any_ip_addresses')
for country in countries_of_all_ips:
    if country == 'some unusual country':
        return True
```

### Available methods

The following tables shows the available methods for the IPinfo Location, ASN and Privacy Objects, their descriptions, and expected return values.

All methods take the argument of the field you are searching for.

#### Location

<table><thead><tr><th width="185">Location method</th><th width="152">Return type</th><th>Example</th></tr></thead><tbody><tr><td>city</td><td>String</td><td>"San Francisco"</td></tr><tr><td>country</td><td>String</td><td>"US"</td></tr><tr><td>latitude</td><td>String</td><td>"37.7812"</td></tr><tr><td>longitude</td><td>String</td><td>"-122.4614"</td></tr><tr><td>postal_code</td><td>String</td><td>"94118"</td></tr><tr><td>region</td><td>String</td><td>"California"</td></tr><tr><td>region_code</td><td>String</td><td>"CA"</td></tr><tr><td>timezone</td><td>String</td><td>"America/Los_Angeles"</td></tr><tr><td>context</td><td>Object</td><td><p>a dictionary that contains all of the above fields with capitalized method name as a key, e.g.: {</p><p>"City":"San Francisco",<br>...</p><p>}</p></td></tr></tbody></table>

#### ASN

<table><thead><tr><th width="152">ASN method</th><th width="137">Return type</th><th width="419">Example</th></tr></thead><tbody><tr><td>asn</td><td>String</td><td>"AS7018"</td></tr><tr><td>domain</td><td>String</td><td>"att.com"</td></tr><tr><td>name</td><td>String</td><td>"AT&#x26;T Services, Inc."</td></tr><tr><td>route</td><td>String</td><td>"107.128.0.0/12"</td></tr><tr><td>type</td><td>String</td><td>"isp"</td></tr><tr><td>context</td><td>Object</td><td><p>a dictionary that contains all of the above fields with capitalized method name as a key, e.g.: {</p><p>"ASN":"AS7018",</p><p>"Domain" : "att.com",<br>...</p><p>}</p></td></tr></tbody></table>

#### Privacy

<table><thead><tr><th width="178.66666666666666">Privacy method</th><th width="138">Return type</th><th>Example</th></tr></thead><tbody><tr><td>hosting</td><td>boolean</td><td>true</td></tr><tr><td>proxy</td><td>boolean</td><td>false</td></tr><tr><td>tor</td><td>boolean</td><td>true</td></tr><tr><td>vpn</td><td>boolean</td><td>false</td></tr><tr><td>relay</td><td>boolean</td><td>true</td></tr><tr><td>service</td><td>string</td><td>"NordVPN"</td></tr></tbody></table>
