Folium Map Plotting

The FoliumMap class is a light wrapper around the Folium geo-mapping interactive mapping package. See Folium.

Folium is itself built on the leaflet.js library.

The msticpy FoliumMap class expects IpAddress entities as input. Each entity must have a valid Location property populated with a GeoLocation object containing the Latitude, Longitude and, optionally, other attributes.

The GeoIP Lookup module classes return IpAddress entities populated with this data so can be used seemlessly with the FoliumMap class.

Display a GeoIP Map

Assuming that you have a set of IpAddress objects with location data populated, you can plot the addresses as follows:

from msticpy.nbtools.foliummap import FoliumMap
folium_map = FoliumMap()

# Set Icon properties to display
icon_props = {"color": "green"}

# Set additional properties to display in tooltips
# in AdditionalData property of IpAddress entities
for ips in host_entity.public_ips:
    ips.AdditionalData["host"] = host_entity.HostName
# Add the IP set to the map
folium_map.add_ip_cluster(ip_entities=host_entity.public_ips, **icon_props)

# display the map (or just have folium_map as the last statement
# of the cell - Jupyter will use display() automatically)
Folium interactive map

Converting IP Address Strings to IpAddress entities

This example uses an function to create IpAddress entities from IP string or ipaddress objects stored in a pandas DataFrame.

The format_ip_entity function converts the IP string value to an IpAddress object, looks up the geolocation (this data is populated into the IpAddress Location attribute). It also adds additional information from the pandas DataFrame into the AdditionalData attribute. Values populated here will be displayed in the tooltip for each plotted IP Address on the map.


The values populated into the AdditionalData attribute are specific to this example. AdditionalData is a dictionary object so you can put data keyed with a string name here. Primitive value types such as string, numbers, dates, etc. should display correctly.

# Create a IP Geolookup class
iplocation = GeoLiteLookup()

def format_ip_entity(row, ip_col):
    ip_entity = entities.IpAddress(Address=row[ip_col])
    ip_entity.AdditionalData["protocol"] = row.L7Protocol
    if "severity" in row:
        ip_entity.AdditionalData["threat severity"] = row["severity"]
    if "Details" in row:
        ip_entity.AdditionalData["threat details"] = row["Details"]
    return ip_entity

ips_out = list(selected_out.apply(lambda x: format_ip_entity(x, "dest"), axis=1))
ips_in = list(selected_in.apply(lambda x: format_ip_entity(x, "source"), axis=1))
ips_threats = list(ti_ip_results.apply(lambda x: format_ip_entity(x, "Ioc"), axis=1))

icon_props = {"color": "green"}
for ips in host_entity.public_ips:
    ips.AdditionalData["host"] = host_entity.HostName
folium_map.add_ip_cluster(ip_entities=host_entity.public_ips, **icon_props)
icon_props = {"color": "blue"}
folium_map.add_ip_cluster(ip_entities=ips_out, **icon_props)
icon_props = {"color": "purple"}
folium_map.add_ip_cluster(ip_entities=ips_in, **icon_props)
icon_props = {"color": "red"}
folium_map.add_ip_cluster(ip_entities=ips_threats, **icon_props)


See also

GeoIP Lookup