Plot search results on a map
This documentation does not apply to the most recent version of Splunk. Click here for the latest version.
Plot search results on a map
Use these instructions to add a map to your view. You must first download and install the Ammap app from Splunkbase to get this working.
These are the basic steps for building a map view:
1. Install the Ammap app: this contains all the supporting libraries you'll need to build your own map.
2. Make a search with the fields required to build the map.
3. Invoke the mapit script.
4. Put your map into Splunk Web by building a view.
Install the Ammap app
The app can be found on Splunkbase here. Install the app the same way you install any other app -- either download it through Launcher, or unzip it into
$SPLUNK_HOME/etc/apps/. Also, you will need to install the supporting MAXMIND app.
Make a search
Once you've installed the app, you'll notice an empty map on the default landing page of this app. That map is set to be populated by your data on an hourly basis, mapping the top 100 public IP addresses in your instance that are recorded in the last hour. If you are running Splunk Free you will need to manually populate this map. To make sure everything is working correctly, run the following search:
* | rex "(?<ip>\d+\.\d+\.\d+\.\d+)"| search ip!=192.168* ip!=0.0.* ip!=10.* | stats count by ip | head 100 | eval count_label="Event" | eval iterator="ip" | eval iterator_label="IP" | eval movie_color="#FF0000" | eval output_file="home_threat_data.xml" | eval app="amMap" | lookup geoip clientip as ip | mapit
If you get back a result count from the above search you should see a populated map. If you do not see anything remove the
| mapit part of the search and run it again to make sure you are getting back a results table with populated geo info. If a table is returning but the geo fields are empty you have most likely do not have any public IPs addresses in your data for the ip2geo translation to operate on.
Build your own search
Now, you can build your own search and save it to run on a schedule, or when you load the view.
First, make sure you have a field called IP. You can either do this by creating a field extraction to save your field, or use the rex expression to extract the field on the fly. It's best practice to create an IP field, either client_ip, src_ip, dest_ip or some other field containing only IP address data. This example searches apache data then applies a filter to remove any internal IP addresses from the search:
sourcetype=apache ip!=192.168* ip!=0.0.* ip!=10.*
This part of the search represents the results you are interested in. You may want to add additional values to have results that represent a particular threat, web traffic or any other data you would like to see represented geographically on the flash map.
Next, create a stats table for that IP field. For example:
| stats count by ip
The next step is to create the required fields necessary for the map_results.py script to run. For example:
| eval count_label="Event" | eval iterator="ip" | eval iterator_label="IP" | eval movie_color="#FF0000" | eval output_file="home_threat_data.xml" | eval app="amMap"
These eval statements create the REQUIRED fields for the map to work:
- count_label: what to display upon mouseover (i.e. Security Events, BotNet events, etc.). In the example above, this is set to "Event."
- iterator: what the script should iterate on. In the example above, this is set to "ip," meaning the script will count all the unique IP addresses for each location.
- iterator_label: give a pretty print name to the iterator. In the example above, this is "IP." This label appears in the mouseover for a location as Unique IP(s).
- movie_color: this is the color of the marker on the map. The example above uses eval and sets the marker to one static color. If you'd like to set a dynamic range of colors, use the rangemap command.
- app: specify an app to write the map data to.
- output_file: name the XML file where the map data will be written to. The output file will go into the
Invoke the script
Now that you have the search down there are a couple of ways to get the map output.
Set up an alert action
If you have a Splunk Enterprise License you can schedule a search and use the alert action map_results.sh. You will need to copy the sh file from the bin/alert_scripts directory of this app into $SPLUNK_HOME/bin/scripts/
Use a search command
Another option to map things on the fly is to use the mapit search command that ships with the Ammap app. The command is exported globally and can be called from any app. Construct a search as described above, and then pipe it to mapit to generate a map on the fly. You can also schedule this search.
Add your map to Splunk Web
You must first copy over various assets from the Ammap app into your app directory.
- Create an empty xml_out directory within the static/ directory to store the results of your search.
Next, edit the HTML. You only need to specify what app you want to generate your map in by setting the correct app in the appropriate HTML file. If you're making a threat map, use threat_map.html, if you're creating a traffic map, use traffic_map.html. Set any instance of /static/app/ammap/ to the path of the app you're working in. For example, change /static/app/ammap/ammap/ to your app's path. The code you're interested in is below:
var so = new SWFObject("/static/app/ammap/ammap/ammap.swf", "ammap", "100%", "350", "8", "#FFFFFF"); so.addVariable("path", "/static/app/ammap/ammap/"); so.addVariable("data_file", escape("/static/app/ammap/xml_out/home_threat_data.xml")); so.addVariable("path", "/static/app/ammap/ammap/"); so.addVariable("settings_file", escape("/static/app/ammap/ammap/ammap_settings.xml"));
Now, build a view in your app that includes the HTML in a ServerSideInclude module. For example:
<view template="dashboard.html"> <label>AMMAP View</label> <module name="AccountBar" layoutPanel="appHeader"/> <module name="AppBar" layoutPanel="navigationHeader"/> <module name="Message" layoutPanel="messaging"> <param name="filter">*</param> <param name="clearOnJobDispatch">False</param> <param name="maxSize">1</param> </module> <module name="TitleBar" layoutPanel="viewHeader"> <param name="actionsMenuFilter">dashboard</param> </module> <module name="SearchBar" layoutPanel="splSearchControls-inline"> <param name="useAssistant">true</param> <param name="useTypeahead">true</param> <param name="useOwnSubmitButton">False</param> <module name="TimeRangePicker"> <param name="selected">All time</param> <param name="searchWhenChanged">True</param> <module name="SubmitButton"> <param name="allowSoftSubmit">True</param> <module name="ViewRedirector" layoutPanel="viewHeader"> <param name="viewTarget">flashtimeline</param> </module> </module> </module> </module> <module name="ServerSideInclude" layoutPanel="panel_row1_col1"> <param name="src">threat_map.html</param> </module> </view>
The map_results log file is indexed into the Splunk _internal index. You can view that log with the following search:
Additional debugging statements can be added by un-commenting anywhere you see logger() being called.
Also, you can call the script from the CLI and pass a search ID. This is helpful for catching exceptions thrown by the script. The usage for this is like so:
$SPLUNK_HOME/bin/splunk cmd python $SPLUNK_HOME/etc/apps/amMap/bin/map_results.py <sid>