Prisma Access Egress IP feed
Dynamically retrieve and add to allow list IPs Prisma Access uses to egress traffic to the internet and SaaS apps.
Data Enrichment & Threat Intelligence · Palo Alto Networks - Strata Cloud Manager · Feed
Details
| ID | Prisma Access Egress IP feed |
|---|---|
| Provider | Palo Alto Networks |
| Category | Data Enrichment & Threat Intelligence |
| From Version | 5.5.0 |
| Docker Image | demisto/python3:3.12.13.10116658 |
| Supported Modules | Agentix Cloud Runtime Security Cloud Posture Security XSIAM EDR Cortex Cloud |
README
Dynamically retrieve and allow IPs Prisma Access uses to egress traffic to the internet and SaaS apps.
Configure Prisma Access Egress IP feed in Cortex
| Parameter | Description | Required |
|---|---|---|
| feed | Fetch indicators | False |
| URL | URL | True |
| api_key | Prisma Access API Key from Panorama | True |
| serviceType | Service Type | True |
| addrType | Address Type | True |
| location | Location | False |
| feedReputation | Indicator Reputation | False |
| feedReliability | Source Reliability | True |
| tlp_color | The Traffic Light Protocol (TLP) designation to apply to indicators fetched from the feed. More information about the protocol can be found at https://us-cert.cisa.gov/tlp | False |
| feedExpirationPolicy | False | |
| feedExpirationInterval | False | |
| feedFetchInterval | Feed Fetch Interval | False |
| feedBypassExclusionList | Bypass exclusion list | False |
| insecure | Trust any certificate (not secure) | False |
| proxy | Use system proxy settings | False |
Retrieve Egress API Key
To retrieve the Egress API key from Panorama - Click “Generate API Key” under Panorama->Cloud Services->Configuration->Service Setup. For more information, see Retrieve the IP Addresses for Prisma Access.
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.
prisma-access-get-indicators
Gets indicators from the feed.
Base Command
prisma-access-get-indicators
Input
| Argument Name | Description | Required |
|---|---|---|
| limit | The maximum number of results to return. By default all IPs are returned. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| PrismaAccess.Egress.IP.Address | string | Prisma Access Egress IP address |
| PrismaAccess.Egress.IP.Zone | string | Prisma Access Egress IP zone |
Command Example
!prisma-access-get-indicators limit=300
Configuration parameters
feed— Fetch indicatorsURL— URL (required)credentials—serviceType— Service TypeaddrType— Address Typelocation— LocationfeedReputation— Indicator ReputationfeedReliability— Source Reliabilitytlp_color— Traffic Light Protocol ColorfeedExpirationPolicy—feedExpirationInterval—feedFetchInterval— Feed Fetch IntervalfeedBypassExclusionList— Bypass exclusion listinsecure— Trust any certificate (not secure)proxy— Use system proxy settingsfeedTags— Tagsapi_key— Prisma Access API Key (Deprecated)
Commands (1)
-
prisma-access-get-indicatorsGets indicators from the feed.
from collections.abc import Callable from typing import Any import demistomock as demisto # noqa: F401 import urllib3 from CommonServerPython import * # noqa: F401 # disable insecure warnings urllib3.disable_warnings() INTEGRATION_NAME = "Prisma Access" class Client(BaseClient): """ Client to use in the Prisma Access Feed integration. Overrides BaseClient. Prisma Access V2 API: https://api.gpcloudservice.com/getPrismaAccessIP/v2 https://docs.paloaltonetworks.com/prisma/prisma-access/prisma-access-panorama-admin/prisma-access-overview/retrieve-ip-addresses-for-prisma-access """ def __init__( self, clientConfigs: list, api_key: str, insecure: bool = False, proxy: bool = False, tags: list | None = [], tlp_color: str | None = None, ): """ Implements class for Prisma Access feed. :param clientConfigs: config data :param insecure: boolean, if *false* feed HTTPS server certificate is verified. Default: *false* :param proxy: boolean, if *false* feed HTTPS server certificate will not use proxies. Default: *false* :param tlp_color: Traffic Light Protocol color. """ self._apiKey = api_key self.tags = [] if tags is None else tags self.tlp_color = tlp_color super().__init__(base_url=clientConfigs, verify=not insecure, proxy=proxy) def build_iterator(self) -> list: """Retrieves all entries from the feed. Returns: A list of objects, containing the indicators. """ result = [] for feed_obj in self._base_url: feed_url = feed_obj.get("FeedURL") postData = feed_obj.get("feedParams", {"serviceType": "all", "addrType": "all", "location": "all"}) try: response = requests.post( url=feed_url, verify=self._verify, headers={"header-api-key": self._apiKey}, data=json.dumps(postData) ) response.raise_for_status() responseData = response.json() prismaStatus = responseData.get("status", "") if prismaStatus == "success": zones = responseData.get("result", []) for z in zones: zoneName = z.get("zone", "") addresses = z.get("addresses", []) for addr in addresses: indicator = {"zone": zoneName, "value": addr, "FeedURL": feed_url} if postData["serviceType"] != "all": indicator["serviceType"] = postData["serviceType"] if postData["addrType"] != "all": indicator["addrType"] = postData["addrType"] result.append(indicator) else: demisto.debug(str(prismaStatus)) raise Exception( f"Non-success status returned from call to {INTEGRATION_NAME}.\n" f"Raw response: " + json.dumps(responseData, indent=2) ) except requests.exceptions.SSLError as err: demisto.debug(str(err)) raise Exception(f"SSL error in the API call to {INTEGRATION_NAME}.\nCheck your not secure parameter.\n\n{err}") except requests.ConnectionError as err: demisto.debug(str(err)) raise Exception( f"Connection error in the API call to {INTEGRATION_NAME}.\nCheck your Server URL parameter.\n\n{err}" ) except requests.exceptions.HTTPError as err: demisto.debug(str(err)) raise Exception(f"HTTP error in the API call to {INTEGRATION_NAME}:\n\n" + str(err)) except ValueError as err: demisto.debug(str(err)) raise ValueError(f"Could not parse returned data to Json. \n\nError message: {err}") return result def test_module(client: Client, *_) -> tuple[str, dict[Any, Any], dict[Any, Any]]: """Builds the iterator to check that the feed is accessible. Args: client: Client object. Returns: Outputs. """ client.build_iterator() return "ok", {}, {} def fetch_indicators(client: Client, limit: int = -1) -> list[dict]: """Retrieves indicators from the feed Args: client: Client object with request limit: limit the results Returns: Indicators. """ iterator = client.build_iterator() indicators = [] if limit > 0: iterator = iterator[:limit] for item in iterator: value = item.get("value") raw_data = { "value": value, "serviceType": item.get("serviceType", ""), "addrType": item.get("addrType", ""), "zone": item.get("zone", ""), } indicator_mapping_fields = {} indicator_mapping_fields["geocountry"] = item.get("zone", "") indicator_mapping_fields["description"] = "IP from Prisma Access Egress API" indicator_mapping_fields["tags"] = client.tags if client.tlp_color: indicator_mapping_fields["trafficlightprotocol"] = client.tlp_color indicators.append( { "value": value, "type": FeedIndicatorType.IP, "rawJSON": raw_data, "fields": indicator_mapping_fields, "zone": item.get("zone", ""), } ) return indicators def get_indicators_command(client: Client, args: dict[str, str]) -> tuple[str, dict[Any, Any], dict[Any, Any]]: """Wrapper for retrieving indicators from the feed to the war-room. Args: client: Client object with request args: demisto.args() Returns: Outputs. """ limit = int(demisto.args().get("limit")) if "limit" in demisto.args() else 0 indicators = fetch_indicators(client, limit) human_readable = tableToMarkdown("Prisma Access Egress IPs:", indicators, headers=["zone", "value"], removeNull=True) outputs = {"PrismaAccess.Egress.IP": [{"Address": ip.get("value", ""), "Zone": ip.get("zone", "")} for ip in indicators]} retIndicators = {"raw_response": indicators} return human_readable, outputs, retIndicators def fetch_indicators_command(client: Client) -> list[dict]: """Wrapper for fetching indicators from the feed to the Indicators tab. Args: client: Client object with request Returns: Indicators. """ indicators = fetch_indicators(client) return indicators def main(): PRISMA_ACCESS_EGRESS_V2_URI = "getPrismaAccessIP/v2" """ PARSE AND VALIDATE INTEGRATION PARAMS """ params = demisto.params() param_api_key = (params.get("credentials") or {}).get("password") or params.get("api_key") if not param_api_key: raise Exception("API Key must be provided.") insecure = params.get("insecure", False) proxy = params.get("proxy") tags = argToList(params.get("feedTags")) tlp_color = params.get("tlp_color") baseURL = params.get("URL") if baseURL[-1] != "/": baseURL += "/" feedURL = baseURL + PRISMA_ACCESS_EGRESS_V2_URI feedParams = { "serviceType": demisto.params().get("serviceType", "all"), "addrType": demisto.params().get("addrType", "all"), "location": demisto.params().get("location", "all"), } clientConfigs = [{"FeedURL": feedURL, "feedParams": feedParams}] command = demisto.command() demisto.info(f"Command being called is {command}") try: client = Client(clientConfigs, param_api_key, insecure, proxy, tags, tlp_color) commands: dict[str, Callable[[Client, dict[str, str]], tuple[str, dict[Any, Any], dict[Any, Any]]]] = { "test-module": test_module, "prisma-access-get-indicators": get_indicators_command, } if command in commands: return_outputs(*commands[command](client, demisto.args())) elif command == "fetch-indicators": indicators = fetch_indicators_command(client) for iter_ in batch(indicators, batch_size=2000): demisto.createIndicators(iter_) else: raise NotImplementedError(f"Command {command} is not implemented.") except Exception as err: err_msg = f"Error in {INTEGRATION_NAME} Integration. [{err}]" return_error(err_msg) if __name__ in ["__main__", "builtin", "builtins"]: main()