Xpanse Feed

Use this feed to retrieve the discovered IPs/domains/certificates from the Cortex Xpanse asset database.

Data Enrichment & Threat Intelligence · Cortex Xpanse · Feed

Details

IDXpanse Feed
ProviderPalo Alto Networks
CategoryData Enrichment & Threat Intelligence
From Version6.10.0
Docker Imagedemisto/python3:3.12.13.10116658

README

Use this feed to retrieve the discovered IPs/Domains/Certificates from Cortex Xpanse asset database.
This integration was integrated and tested with version 2.5 of Cortex Xpanse.

Configure Xpanse Feed in Cortex

Parameter Description Required
Server URL The web UI with `api-` appended to front (e.g., https://api-xsiam.paloaltonetworks.com). For more information, see https://docs.paloaltonetworks.com/cortex/cortex-xdr/cortex-xdr-api/cortex-xdr-api-overview/get-started-with-cortex-xdr-apis. True
API Key ID For more information, see https://docs.paloaltonetworks.com/cortex/cortex-xdr/cortex-xdr-api/cortex-xdr-api-overview/get-started-with-cortex-xdr-apis. Only standard API key type is supported. True
API Key   True
Fetch indicators   False
Indicator Reputation Indicators from this integration instance will be marked with this reputation. False
Source Reliability Reliability of the source providing the intelligence data. True
Traffic Light Protocol Color The Traffic Light Protocol (TLP) designation to apply to indicators fetched from the feed. False
    False
Bypass exclusion list When selected, the exclusion list is ignored for indicators from this feed. This means that if an indicator from this feed is on the exclusion list, the indicator might still be added to the system. False
Use system proxy settings   False
Trust any certificate (not secure)   False
Tags Supports CSV values. False
    False
Feed Fetch Interval   False
Indicators types to fetch Indicator types to fetch. True

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.

xpanse-get-indicators


Retrieves a limited number of indicators.

Base Command

xpanse-get-indicators

Input

Argument Name Description Required
limit The maximum number of indicators to return. Required
ip Retrieve discovered IPs. Default is yes. Optional
domain Retrieve discovered domains. Default is yes. Optional
certificate Retrieve discovered certificates. Default is yes. Optional

Context Output

Path Type Description
ASM.Indicators.Name String The name of the indicator.
ASM.Indicators.Description String The description of the indicator.
ASM.Indicators.Type String The type of the indicator.

Command example

!xpanse-get-indicators limit=1 ip=yes certificate=no domain=no

Context Example

{
    "ASM": {
        "Indicators": {
            "Description": "1.1.1.1 indicator of asset type IP from Cortex Xpanse",
            "Name": "1.1.1.1",
            "Type": "IP"
        }
    }
}

Human Readable Output

Xpanse indicators

Name Type Description
1.1.1.1 IP 1.1.1.1 indicator of asset type IP from Cortex Xpanse

Configuration parameters

  • url — Server URL (required)
  • credentials — API Key ID (required)
  • feed — Fetch indicators
  • feedReputation — Indicator Reputation
  • feedReliability — Source Reliability (required)
  • tlp_color — Traffic Light Protocol Color
  • feedExpirationInterval
  • feedBypassExclusionList — Bypass exclusion list
  • proxy — Use system proxy settings
  • insecure — Trust any certificate (not secure)
  • feedTags — Tags
  • feedExpirationPolicy
  • feedFetchInterval — Feed Fetch Interval
  • indicatorTypes — Indicator types to fetch

Commands (1)

  • xpanse-get-indicators

    Retrieves a limited number of indicators.

"""
Tests module for Xpanse Feed integration.
"""

# Client for multiple tests
from FeedXpanse import Client

client = Client(
    base_url="https://test.com",
    tlp_color="GREEN",
    verify=True,
    feed_tags=["test_tag"],
    headers={"HOST": "test.com", "Authorizatio": "THISISAFAKEKEY", "Content-Type": "application/json"},
    proxy=False,
)


def test_map_indicator_type():
    """Tests map_indicator_type helper function.

    Given:
        - Indicator type input
    When:
        - Getting output from map_indicator_type helper function
    Then:
        - Checks the output of the helper function with the expected output.
    """
    from FeedXpanse import map_indicator_type

    # Test know types
    assert map_indicator_type("UNASSOCIATED_RESPONSIVE_IP") == "IP"
    assert map_indicator_type("DOMAIN") == "Domain"
    assert map_indicator_type("CERTIFICATE") == "X509 Certificate"
    assert map_indicator_type("CIDR") == "CIDR"
    # test_map_unknown_type
    assert map_indicator_type("UNKNOWN_TYPE") == "None"
    # test_map_empty_string
    assert map_indicator_type("") == "None"
    # test_map_none_input
    assert map_indicator_type("domain") == "None"


def test_create_x509_certificate_grids():
    """Tests create_x509_certificate_grids helper function.

    Given:
        - Indicator type input
    When:
        - Getting output from create_x509_certificate_grids helper function
    Then:
        - Checks the output of the helper function with the expected output.
    """
    from FeedXpanse import create_x509_certificate_grids

    # test_with_valid_string
    input_str = "C=ZA,ST=Western Cape,L=Cape Town,O=Thawte"
    expected_output = [
        {"title": "C", "data": "ZA"},
        {"title": "ST", "data": "Western Cape"},
        {"title": "L", "data": "Cape Town"},
        {"title": "O", "data": "Thawte"},
    ]
    assert create_x509_certificate_grids(input_str) == expected_output

    # test_with_none_input
    assert create_x509_certificate_grids(None) == []

    # test_with_empty_string
    assert create_x509_certificate_grids("") == []


def test_map_indicator_fields():
    """Tests map_indicator_fields helper function.

    Given:
        - Indicator type input
    When:
        - Getting output from map_indicator_fields helper function
    Then:
        - Checks the output of the helper function with the expected output.
    """
    from FeedXpanse import map_indicator_fields

    # test_map_indicator_fields_domain
    raw_indicator = {
        "name": "example.com",
        "domain_details": {
            "creationDate": 1609459200,
            "registryExpiryDate": 1609459200,
        },
    }
    asset_type = "Domain"
    expected_output = {
        "internal": True,
        "description": "example.com indicator of asset type Domain from Cortex Xpanse",
        "creationdate": "1970-01-19T15:04:19.000Z",
        "expirationdate": "1970-01-19T15:04:19.000Z",
    }
    assert map_indicator_fields(raw_indicator, asset_type) == expected_output

    # test_map_indicator_fields_x509_certificate
    raw_indicator = {
        "name": "certificate",
        "certificate_details": {
            "signatureAlgorithm": "SHA256WithRSAEncryption",
            "serialNumber": "1234567890",
            "validNotAfter": 1609459200,
            "validNotBefore": 1609459200,
            "issuer": "C=US,ST=California",
            "subject": "C=US,ST=California",
        },
    }
    asset_type = "X509 Certificate"
    expected_output = {
        "internal": True,
        "description": "certificate indicator of asset type X509 Certificate from Cortex Xpanse",
        "signaturealgorithm": "SHA256WithRSAEncryption",
        "serialnumber": "1234567890",
        "validitynotafter": "1970-01-19T15:04:19.000Z",
        "validitynotbefore": "1970-01-19T15:04:19.000Z",
        "issuer": [{"title": "C", "data": "US"}, {"title": "ST", "data": "California"}],
        "subject": [{"title": "C", "data": "US"}, {"title": "ST", "data": "California"}],
    }
    assert map_indicator_fields(raw_indicator, asset_type) == expected_output


def test_build_asset_indicators():
    """Tests build_asset_indicators helper function.

    Given:
        - Indicator type input
    When:
        - Getting output from build_asset_indicators helper function
    Then:
        - Checks the output of the helper function with the expected output.
    """
    from FeedXpanse import build_asset_indicators

    # test_build_asset_indicators
    raw_indicators = [
        {"name": "example.com", "asset_type": "DOMAIN"},
        {"name": "example.net", "asset_type": "DOMAIN", "ipv6s": ["::1"]},  # This should be skipped
        {"name": "*.example.org", "asset_type": "DOMAIN"},  # This should become a DomainGlob
        {"name": "nonexistent", "asset_type": "CLOUD_SERVER"},  # This should be skipped
    ]
    expected_output = [
        {
            "value": "example.com",
            "type": "Domain",
            "fields": {
                "internal": True,
                "description": "example.com indicator of asset type Domain from Cortex Xpanse",
                "trafficlightprotocol": "GREEN",
                "tags": ["test_tag"],
            },
            "rawJSON": {"name": "example.com", "asset_type": "DOMAIN"},
        },
        {
            "value": "*.example.org",
            "type": "DomainGlob",
            "fields": {
                "internal": True,
                "description": "*.example.org indicator of asset type DomainGlob from Cortex Xpanse",
                "trafficlightprotocol": "GREEN",
                "tags": ["test_tag"],
            },
            "rawJSON": {"name": "*.example.org", "asset_type": "DOMAIN"},
        },
    ]
    assert build_asset_indicators(client, raw_indicators) == expected_output


def test_fetch_indicators(mocker):
    """Tests fetch_indicators command function.

    Given:
        - requests_mock instance to generate the appropriate list_asset_internet_exposure_command( API response,
          loaded from a local JSON file.
    When:
        - Getting output from fetch_indicators command function
    Then:
        - Checks the output of the command function with the expected output.
    """
    from FeedXpanse import fetch_indicators
    from test_data.raw_response import EXTERNAL_EXPOSURES_RESPONSE

    mocker.patch.object(client, "list_asset_internet_exposure_request", return_value=EXTERNAL_EXPOSURES_RESPONSE)
    indicators, _ = fetch_indicators(client, limit=1, asset_type="domain")
    expected_indicators_fields = {
        "internal": True,
        "description": "example.com indicator of asset type Domain from Cortex Xpanse",
        "trafficlightprotocol": "GREEN",
        "tags": ["test_tag"],
    }
    assert indicators[0]["fields"] == expected_indicators_fields


def test_get_indicators(mocker):
    """Tests get_indicators command function.

    Given:
        - requests_mock instance to generate the appropriate list_asset_internet_exposure_command( API response,
          loaded from a local JSON file.
    When:
        - Getting output from get_indicators command function
    Then:
        - Checks the output of the command function with the expected output.
    """
    from FeedXpanse import get_indicators
    from test_data.raw_response import EXTERNAL_EXPOSURES_RESPONSE

    mocker.patch.object(client, "list_asset_internet_exposure_request", return_value=EXTERNAL_EXPOSURES_RESPONSE)
    args = {"limit": "1", "domain": "yes", "certificate": "no", "ipv4": "no"}
    response = get_indicators(client, args)
    assert response.outputs[0]["Type"] == "Domain"