McAfee DXL

McAfee DXL client.

Messaging and Conferencing · McAfee DXL

Details

IDMcAfee DXL
ProviderTrellix
CategoryMessaging and Conferencing
From Version5.0.0
Docker Imagedemisto/dxl:1.0.0.10133006
Supported ModulesAgentix XSIAM

README

Use the McAfee DXL integration to connect and optimize security actions across multiple vendor products.

How to Create the RSA Key Pair

Before you configure the ePO server, you need to generate the RSA key pair. Make sure that openssl is installed.

  1. Open a new directory.
  2. Download the sh script and move it to the new directory.
  3. Run the script.
  4. Complete the required fields, except the challenge password and the optional company name (leave empty).
    The certificate (client.crt) is valid for 365 days (you can change the value in the script).

After the script finishes running, you should have the following files.
- client.key (private key)
- client.crt (public key)
- client.csr (certificate request that is not required for the configuration flow)

Configure the ePO Server

To configure the ePO server, you need to upload the public key.

  1. In ePO server go to Menu > Server Settings.
    go to menu
    go to server settings
  2. Under DXL certificates (Third Party) click Edit.
    click edit
  3. download the brokers certificate.
    export Broker certificates
  4. Download the brokers list.
    export Broker list
  5. Click Import and select the client.crt file.
    click import
    select client.crt file
    click ok
  6. Click Save.
    click save
  7. Test the integration (it may take a few minutes until the key is enabled).

Configure McAfee DXL on Cortex XSOAR

  1. Navigate to Settings > Integrations > Servers & Services.
  2. Search for McAfee DXL.
  3. Click Add instance to create and configure a new integration instance.
Parameter Description Required
broker_ca_bundle Broker CA certificates content (see brokercerts.crt in the instructions). True
cert_file Client certificates content (see client.crt in the instructions). True
private_key Client private key content (e.g. client.key) True
broker_urls Brokers URLs (comma separated list in the form of [ssl://]<hostname>[:port]). Get the hostname & port from the brokerlist.properties file in the instructions. Note that the broker should be reachable from the Cortex XSOAR server. True
push_ip_topic The topic for which to publish the ‘dxl-push-ip’. False
push_url_topic The topic for which to publish the ‘dxl-push-url’. False
push_domain_topic The topic for which to publish the ‘dxl-push-domain’. False
push_hash_topic The topic for which to publish the ‘dxl-push-hash’. False
  1. Click Test to validate the URLs, token, and connection.

Commands

You can execute these commands from the Cortex XSOAR 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.

1. Send an event to DXL


Sends the specified event to the DXL fabric.

Base Command

dxl-send-event

Input
Argument Name Description Required
topic The topic for which to publish the message. Required
payload The event payload. Required
Context Output

There is no context output for this command.

Command Example

dxl-send-event topic="TOPIC_NAME" payload="The message"

Human Readable Output

Successfully sent event

2. Push an IP address to DXL


Pushes an IP address to the DXL fabric.

Base Command

dxl-push-ip

Input
Argument Name Description Required
ip The IP address to push to the DXL fabric. Required
trust_level The new trust level for the IP address. Can be: “NOT_SET”, “KNOWN_MALICIOUS”, “MOST_LIKELY_MALICIOUS”, “UNKNOWN”, “MIGHT_BE_TRUSTED”, “MOST_LIKELY_TRUSTED”, “KNOWN_TRUSTED”, or “KNOWN_TRUSTED_INSTALLER”. Required
topic The topic for which to publish the ‘dxl-push-ip’. Optional
Context Output

There is no context output for this command.

Command Example

dxl-push-ip ip="104.196.188.170" trust_level="KNOWN_TRUSTED" topic="IP_LISTENER"

Human Readable Output

Successfully pushed ip 104.196.188.170 with trust level KNOWN_TRUSTED

3. Push the URL to DXL


Pushes the URL to the DXL fabric.

Base Command

dxl-push-url

Input
Argument Name Description Required
url The URL to push to the DXL fabric. Required
trust_level The new trust level for the URL. Can be: “NOT_SET”, “KNOWN_MALICIOUS”, “MOST_LIKELY_MALICIOUS”, “UNKNOWN”, “MIGHT_BE_TRUSTED”, “MOST_LIKELY_TRUSTED”, “KNOWN_TRUSTED”, or “KNOWN_TRUSTED_INSTALLER”. Required
topic The topic for which to publish the ‘dxl-push-url’. Optional
Context Output

There is no context output for this command.

Command Example

dxl-push-url url="https://www.demisto.com" trust_level="KNOWN_TRUSTED" topic="URL_LISTENER"

Human Readable Output

Successfully pushed URL https://www.demisto.com with trust level KNOWN_TRUSTED

4. Push a domain to DXL


Pushes a domain to the DXL fabric

Base Command

dxl-push-domain

Input
Argument Name Description Required
domain The domain to push to the DXL fabric. Required
trust_level The new trust level for the domain. Can be: “NOT_SET”, “KNOWN_MALICIOUS”, “MOST_LIKELY_MALICIOUS”, “UNKNOWN”, “MIGHT_BE_TRUSTED”, “MOST_LIKELY_TRUSTED”, “KNOWN_TRUSTED”, or “KNOWN_TRUSTED_INSTALLER”. Required
topic The topic for which to publish the ‘dxl-push-domain’. Optional
Context Output

There is no context output for this command.

Command Example

dxl-push-domain domain="demisto.com" trust_level="KNOWN_TRUSTED" topic="DOMAIN_LISTENER"

Human Readable Output

Successfully pushed domain demisto.com with trust level KNOWN_TRUSTED

5. Push a file hash to DXL


Pushes a file hash to the DXL fabric.

Base Command

dxl-push-hash

Input
Argument Name Description Required
hash The hash to push to the DXL fabric. Required
trust_level The new trust level for the domain. Can be: “NOT_SET”, “KNOWN_MALICIOUS”, “MOST_LIKELY_MALICIOUS”, “UNKNOWN”, “MIGHT_BE_TRUSTED”, “MOST_LIKELY_TRUSTED”, “KNOWN_TRUSTED”, or “KNOWN_TRUSTED_INSTALLER”. Required
topic The topic for which to publish the ‘dxl-push-hash’. Optional
Context Output

There is no context output for this command.

Command Example

dxl-push-hash hash="HASH_TO_SEND" trust_level="KNOWN_TRUSTED" topic="HASH_LISTENER"

Human Readable Output

Successfully pushed hash HASH_TO_SEND with trust level KNOWN_TRUSTED

Configuration parameters

  • broker_ca_bundle — Broker CA certificates content (see `brokercerts.crt` in the instructions). (required)
  • cert_file — Client certificates content (see `client.crt` in the instructions). (required)
  • private_key — Client private key content (e.g. `client.key`) (required)
  • broker_urls — Brokers URLs (comma separated list in the form of [ssl://]<hostname>[:port]). Get the hostname & port from the `brokerlist.properties` file in the instructions. Note that the broker should be reachable from the Demisto server. (required)
  • push_ip_topic — The topic for which to publish the 'dxl-push-ip'.
  • push_url_topic — The topic for which to publish the 'dxl-push-url'.
  • push_domain_topic — The topic for which to publish the 'dxl-push-domain'.
  • push_hash_topic — The topic for which to publish the 'dxl-push-hash'.

Commands (5)

  • dxl-push-domain

    The push domain to the DXL fabric.

  • dxl-push-hash

    The push hash to the DXL fabric.

  • dxl-push-ip

    The push IP address to the DXL fabric.

  • dxl-push-url

    The push URL to the DXL fabric.

  • dxl-send-event

    Sends the specified event to the DXL fabric.

import tempfile
import demistomock as demisto  # noqa: F401
from CommonServerPython import *  # noqa: F401
from dxlclient.broker import Broker
from dxlclient.client import DxlClient
from dxlclient.client_config import DxlClientConfig
from dxlclient.message import Event

from CommonServerUserPython import *

INTEGRATION_NAME = "McAfee DXL"
CONNECT_RETRIES = 1
RECONNECT_DELAY = 1
RECONNECT_DELAY_MAX = 10


class EventSender:
    TRUST_LEVEL = {
        "NOT_SET": "0",
        "KNOWN_MALICIOUS": "1",
        "MOST_LIKELY_MALICIOUS": "15",
        "MIGHT_BE_MALICIOUS": "30",
        "UNKNOWN": "50",
        "MIGHT_BE_TRUSTED": "70",
        "MOST_LIKELY_TRUSTED": "85",
        "KNOWN_TRUSTED": "99",
        "KNOWN_TRUSTED_INSTALLER": "100",
    }
    broker_ca_bundle = tempfile.NamedTemporaryFile().name
    cert_file = tempfile.NamedTemporaryFile().name
    private_key = tempfile.NamedTemporaryFile().name

    def __init__(self, params: dict):
        with open(self.broker_ca_bundle, "w") as text_file:
            text_file.write(params["broker_ca_bundle"])
        with open(self.cert_file, "w") as text_file:
            text_file.write(params["cert_file"])
        with open(self.private_key, "w") as text_file:
            text_file.write(params["private_key"])

        if "broker_urls" in params:
            self.broker_urls = params["broker_urls"].split(",")
        self.push_ip_topic = params.get("push_ip_topic")
        self.push_url_topic = params.get("push_url_topic")
        self.push_domain_topic = params.get("push_domain_topic")
        self.push_hash_topic = params.get("push_hash_topic")
        self.client = DxlClient(self.get_client_config())
        self.client.connect()

    def __del__(self):
        self.client.disconnect()

    def push_ip(self, ip, trust_level, topic):
        if not is_ip_valid(ip):
            raise ValueError(f"argument ip {ip} is not a valid IP")

        trust_level_key = self.TRUST_LEVEL[trust_level]
        if topic:
            self.push_ip_topic = topic

        self.send_event(self.push_ip_topic, f"ip:{ip};trust_level:{trust_level_key}")
        return f"Successfully pushed ip {ip} with trust level {trust_level}"

    def push_url(self, url, trust_level, topic):
        trust_level_key = self.TRUST_LEVEL[trust_level]
        if topic:
            self.push_url_topic = topic

        self.send_event(self.push_url_topic, f"url:{url};trust_level:{trust_level_key}")
        return f"Successfully pushed url {url} with trust level {trust_level}"

    def push_domain(self, domain, trust_level, topic):
        trust_level_key = self.TRUST_LEVEL[trust_level]
        if topic:
            self.push_domain_topic = topic

        self.send_event(self.push_domain_topic, f"domain:{domain};trust_level:{trust_level_key}")
        return f"Successfully pushed domain {domain} with trust level {trust_level}"

    def push_hash(self, hash_obj, trust_level, topic):
        trust_level_key = self.TRUST_LEVEL[trust_level]
        if topic:
            self.push_ip_topic = topic

        self.send_event(self.push_hash_topic, f"hash:{hash_obj};trust_level:{trust_level_key}")
        return f"Successfully pushed hash {hash_obj} with trust level {trust_level}"

    def get_client_config(self):
        config = DxlClientConfig(
            broker_ca_bundle=self.broker_ca_bundle,
            cert_file=self.cert_file,
            private_key=self.private_key,
            brokers=[Broker.parse(url) for url in self.broker_urls],
        )
        config.connect_retries = CONNECT_RETRIES
        config.reconnect_delay = RECONNECT_DELAY
        config.reconnect_delay_max = RECONNECT_DELAY_MAX
        return config

    def send_event(self, topic, payload):
        if not topic:
            raise Exception(f"Error in {demisto.command()} topic field is required")

        event = Event(topic)
        event.payload = str(payload).encode()
        self.client.send_event(event)

    def send_event_wrapper(self, topic, payload):
        self.send_event(topic, payload)
        return "Successfully sent event"


def validate_certificates_format():
    if "-----BEGIN PRIVATE KEY-----" not in demisto.params()["private_key"]:
        return_error("The private key content seems to be incorrect as it doesn't start with -----BEGIN PRIVATE KEY-----")
    if "-----END PRIVATE KEY-----" not in demisto.params()["private_key"]:
        return_error("The private key content seems to be incorrect as it doesn't end with -----END PRIVATE KEY-----")
    if "-----BEGIN CERTIFICATE-----" not in demisto.params()["cert_file"]:
        return_error(
            "The client certificates content seem to be incorrect as they don't start with '-----BEGIN CERTIFICATE-----'"
        )
    if "-----END CERTIFICATE-----" not in demisto.params()["cert_file"]:
        return_error("The client certificates content seem to be incorrect as it doesn't end with -----END CERTIFICATE-----")
    if not demisto.params()["broker_ca_bundle"].lstrip(" ").startswith("-----BEGIN CERTIFICATE-----"):
        return_error("The broker certificate seem to be incorrect as they don't start with '-----BEGIN CERTIFICATE-----'")
    if not demisto.params()["broker_ca_bundle"].rstrip(" ").endswith("-----END CERTIFICATE-----"):
        return_error("The broker certificate seem to be incorrect as they don't end with '-----END CERTIFICATE-----'")


def main():
    args = demisto.args()
    command = demisto.command()
    try:
        event_sender = EventSender(demisto.params())
        result = ""
        if command == "test-module":
            event_sender.send_event("TEST", "test")
            result = "ok"
        elif command == "dxl-send-event":
            result = event_sender.send_event_wrapper(args.get("topic"), args.get("payload"))
        elif command == "dxl-push-ip":
            result = event_sender.push_ip(args.get("ip"), args.get("trust_level"), args.get("topic"))
        elif command == "dxl-push-url":
            result = event_sender.push_url(args.get("url"), args.get("trust_level"), args.get("topic"))
        elif command == "dxl-push-domain":
            result = event_sender.push_domain(args.get("domain"), args.get("trust_level"), args.get("topic"))
        elif command == "dxl-push-hash":
            result = event_sender.push_hash(args.get("hash"), args.get("trust_level"), args.get("topic"))
        else:
            raise Exception(f"{demisto.command()} is not a command")

        return_outputs(result)
    except Exception as error:
        validate_certificates_format()
        return_error(f"error in {INTEGRATION_NAME} {error!s}.", error)


if __name__ in ("__builtin__", "builtins"):
    main()