SpurContextAPI

Enrich indicators using the Spur Context API.

Data Enrichment & Threat Intelligence · Spur Context API

Details

IDSpurContextAPI
ProviderGoAhead Inc
CategoryData Enrichment & Threat Intelligence
From Version6.10.0
Docker Imagedemisto/python3:3.12.13.10116658
Supported ModulesAgentix XSIAM

README

Enrich indicators using the Spur Context API.
This integration was integrated and tested with version 2 of SpurContextAPI.

Configure SpurContextAPI in Cortex

Parameter Description Required
Server URL (e.g. https://api.spur.us/)   False
API Token   True
Source Reliability Reliability of the source providing the intelligence data. 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.

spur-context-api-enrich


Enrich indicators using the Spur Context API.

Base Command

spur-context-api-enrich

Input

Argument Name Description Required
ip IP address to enrich. Required

Context Output

Path Type Description
SpurContextAPI.Context.ip string IP that was enriched
SpurContextAPI.Context.as object Autonomous System details for an IP Address.
SpurContextAPI.Context.organization string The organization using this IP address.
SpurContextAPI.Context.infrastructure string The primary infrastructure type that this IP address supports. Common tags are MOBILE and DATACENTER.
SpurContextAPI.Context.location object Data-center or IP Hosting location based on MaxMind GeoLite.
SpurContextAPI.Context.services array The different types of proxy or VPN services that are running on this IP address
SpurContextAPI.Context.tunnels array Different VPN or proxy tunnels that are currently in-use on this IP address
SpurContextAPI.Context.risks array Risks that we have determined based on our collection of data.
SpurContextAPI.Context.client_concentration object The strongest location concentration for clients using this IP address.
SpurContextAPI.Context.client_countries number The number of countries that we have observed clients located in for this IP address
SpurContextAPI.Context.client_spread number The total geographic area in kilometers where we have observed users
SpurContextAPI.Context.client_proxies array The different types of callback proxies we have observed on clients using this IP address.
SpurContextAPI.Context.client_count number The average number of clients we observe on this IP address.
SpurContextAPI.Context.client_behaviors array An array of behavior tags for an IP Address.
SpurContextAPI.Context.client_types array The different type of client devices that we have observed on this IP address.

ip


IP reputation command using the Spur Context API.

Base Command

ip

Input

Argument Name Description Required
ip IP address to enrich. Required

Context Output

Path Type Description
DBotScore.Score string The actual score.
DBotScore.Indicator string The indicator that was tested.
DBotScore.Type string The indicator type.
DBotScore.Vendor string The vendor used to calculate the score.
DBotScore.Reliability String Reliability of the source providing the intelligence data.
IP.Address string IP address.
IP.ASN string The autonomous system name for the IP address, for example: “AS8948”.
IP.ASOwner String The autonomous system owner of the IP.
IP.ClientTypes array The organization name.
IP.Geo.Country string The country in which the IP address is located.
IP.Organization.Name string The organization name.
IP.Risks array Risks that we have determined based on our collection of data.
IP.Tunnels array The different types of proxy or VPN services that are running on this IP address.
SpurContextAPI.Context.ip string IP that was enriched.
SpurContextAPI.Context.as object Autonomous System details for an IP Address.
SpurContextAPI.Context.organization string The organization using this IP address.
SpurContextAPI.Context.infrastructure string The primary infracstructure type that this IP address supports. Common tags are MOBILE and DATACENTER.
SpurContextAPI.Context.location object Data-center or IP Hosting location based on MaxMind GeoLite.
SpurContextAPI.Context.services array The different types of proxy or VPN services that are running on this IP address.
SpurContextAPI.Context.tunnels array Different VPN or proxy tunnels that are currently in-use on this IP address.
SpurContextAPI.Context.risks array Risks that we have determined based on our collection of data.
SpurContextAPI.Context.client_concentration object The strongest location concentration for clients using this IP address.
SpurContextAPI.Context.client_countries number The number of countries that we have observed clients located in for this IP address.
SpurContextAPI.Context.client_spread number The total geographic area in kilometers where we have observed users.
SpurContextAPI.Context.client_proxies array The different types of callback proxies we have observed on clients using this IP address.
SpurContextAPI.Context.client_count number The average number of clients we observe on this IP address.
SpurContextAPI.Context.client_behaviors array An array of behavior tags for an IP Address.
SpurContextAPI.Context.client_types array The different type of client devices that we have observed on this IP address.

Configuration parameters

  • base_url — Server URL (e.g. https://api.spur.us/)
  • credentials — (required)
  • reliability — Source Reliability
  • proxy — Use system proxy settings

Commands (2)

  • ip

    IP reputation command using the Spur Context API.

  • spur-context-api-enrich

    Enrich indicators using the Spur Context API.

"""SpurContextAPI Integration for Cortex XSOAR - Unit Tests file

This file contains the Unit Tests for the SpurContextAPI Integration based
on pytest. Cortex XSOAR contribution requirements mandate that every
integration should have a proper set of unit tests to automatically
verify that the integration is behaving as expected during CI/CD pipeline.

Test Execution
--------------

Unit tests can be checked in 3 ways:
- Using the command `lint` of demisto-sdk. The command will build a dedicated
  docker instance for your integration locally and use the docker instance to
  execute your tests in a dedicated docker instance.
- From the command line using `pytest -v` or `pytest -vv`
- From PyCharm

Example with demisto-sdk (from the content root directory):
demisto-sdk lint -i Packs/HelloWorld/Integrations/HelloWorld

Coverage
--------

There should be at least one unit test per command function. In each unit
test, the target command function is executed with specific parameters and the
output of the command function is checked against an expected output.

Unit tests should be self contained and should not interact with external
resources like (API, devices, ...). To isolate the code from external resources
you need to mock the API of the external resource using pytest-mock:
https://github.com/pytest-dev/pytest-mock/

In the following code we configure requests-mock (a mock of Python requests)
before each test to simulate the API calls to the HelloWorld API. This way we
can have full control of the API behavior and focus only on testing the logic
inside the integration code.

We recommend to use outputs from the API calls and use them to compare the
results when possible. See the ``test_data`` directory that contains the data
we use for comparison, in order to reduce the complexity of the unit tests and
avoding to manually mock all the fields.

NOTE: we do not have to import or build a requests-mock instance explicitly.
requests-mock library uses a pytest specific mechanism to provide a
requests_mock instance to any function with an argument named requests_mock.

More Details
------------

More information about Unit Tests in Cortex XSOAR:
https://xsoar.pan.dev/docs/integrations/unit-testing

"""

import pytest
from SpurContextAPI import Client, Common, DBotScoreType, SpurIP, enrich_command, ip_command, main, test_module

# Sample API response for testing
MOCK_HTTP_RESPONSE = {
    "as": {"number": 30083, "organization": "AS-30083-GO-DADDY-COM-LLC"},
    "client": {
        "behaviors": ["TOR_PROXY_USER"],
        "concentration": {
            "city": "Weldon Spring",
            "country": "US",
            "density": 0.202,
            "geohash": "9yz",
            "skew": 45,
            "state": "Missouri",
        },
        "count": 14,
        "countries": 1,
        "proxies": ["LUMINATI_PROXY", "SHIFTER_PROXY"],
        "spread": 4941431,
        "types": ["MOBILE", "DESKTOP"],
    },
    "infrastructure": "DATACENTER",
    "ip": "1.1.1.1",
    "location": {"city": "St Louis", "country": "US", "state": "Missouri"},
    "risks": ["WEB_SCRAPING", "TUNNEL"],
    "services": ["IPSEC", "OPENVPN"],
    "tunnels": [{"anonymous": True, "entries": ["1.1.1.1"], "exits": ["1.1.1.1"], "operator": "NORD_VPN", "type": "VPN"}],
}


@pytest.fixture()
def client(mocker):
    client = Client(base_url="https://api.spur.us/", verify=False, headers={"Authorization": "Bearer test"})
    mocker.patch.object(Client, "_http_request", return_value=MOCK_HTTP_RESPONSE)
    return client


def test_enrich_command(client):
    args = {"ip": "1.1.1.1"}
    result = enrich_command(client, args)
    assert result.outputs["ip"] == MOCK_HTTP_RESPONSE["ip"]


def test_ip_command(client):
    args = {"ip": "1.1.1.1"}
    results = ip_command(client, args)[0]
    assert isinstance(results.indicator, SpurIP)
    assert results.indicator.risks == MOCK_HTTP_RESPONSE["risks"]


def test_test_module(client):
    result = test_module(client)
    assert result == "ok"


def test_spur_ip_to_context():
    ip = "1.1.1.1"
    asn = "AS12345"
    as_owner = "Test AS"
    client_types = ["MOBILE", "DESKTOP"]
    risks = ["WEB_SCRAPING", "TUNNEL"]
    tunnels = {"type": "VPN", "operator": "NORD_VPN", "anonymous": True, "entries": ["1.1.1.1"], "exits": ["1.1.1.1"]}
    ip_indicator = SpurIP(
        ip=ip,
        asn=asn,
        as_owner=as_owner,
        client_types=client_types,
        dbot_score=Common.DBotScore(
            indicator=ip,
            indicator_type=DBotScoreType.IP,
            integration_name="SpurContextAPI",
            score=Common.DBotScore.NONE,
        ),
        risks=risks,
        tunnels=tunnels,
    )

    context = ip_indicator.to_context()
    context_path = context[Common.IP.CONTEXT_PATH]

    assert context_path["Address"] == ip
    assert context_path["ASN"] == asn
    assert context_path["ASOwner"] == as_owner
    assert context_path["Risks"] == risks
    assert context_path["ClientTypes"] == client_types
    assert context_path["Tunnels"] == tunnels


def test_main_enrich_command(mocker):
    mocker.patch("SpurContextAPI.demisto.command", return_value="spur-context-api-enrich")
    mocker.patch("SpurContextAPI.demisto.args", return_value={"ip": "1.1.1.1"})
    mock_enrich = mocker.patch("SpurContextAPI.enrich_command")
    mocker.patch("SpurContextAPI.return_results")
    main()

    mock_enrich.assert_called_once_with(mocker.ANY, {"ip": "1.1.1.1"})