ActiveMQ

Integration with ActiveMQ queue.

Messaging and Conferencing · ActiveMQ

Details

IDActiveMQ
ProviderOpen Source
CategoryMessaging and Conferencing
From Version5.0.0
Docker Imagedemisto/py3-tools:1.0.0.10404775
Supported ModulesAgentix XSIAM

README

Overview


Integration with ActiveMQ.
This integration uses ActiveMQ STOMP protocol, that must be enabled (usually port 61613 by default) in order to work.
Fetch incidents is based on using Durable Topic Subscribers, in order to fetch messages, and convert to Cortex XSOAR incidents.

Use Cases


  • Send messages to queue or topic
  • Read messages from queue or topic
  • Fetch messages from queue or topic and create incidents in Cortex XSOAR per message

Configure ActiveMQ in Cortex


Parameter Description Required
hostname Server IP Address (e.g., 192.168.0.1) True
port Port False
proxy Use system proxy settings False
client-id Client ID False
credentials Username False
client_cert Client certificate (.pem) False
client_key Client certificate key (.key) False
root_ca Root Certificate False
subscription-id Subscription ID False
isFetch Fetch incidents False
incidentType Incident type False
topic-name Topic Name (for subscription) False
queue_name Queue Name (for subscription) False

Fetched Incidents Data


Returns the messages in the queue or topic. Creates incidents in Cortex XSOAR and populate the incident details field
with the message content.

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.

  1. activemq-send
  2. activemq-subscribe

1. activemq-send


Sends a message to the specified destination.

Base Command

activemq-send

Input
Argument Name Description Required
destination The message destination. For example, a message queue in the format: “/queue/test”, or a message topic. Required
body The content of the message to send. Required
headers The customer headers for the message, in the format: {XCorrelationId: uid, nosotros generamos XReplyTo demisto:es:connectors, XType com.elevenpaths.sandas.ra.connector.CreateTicketConnectorRequest, XVersion : “3.0”, persistent : True} Optional
Context Output

There is no context output for this command.

Command Example

!activemq-send destination="/topic/demisto-test" body="send the message to topic"

!activemq-send destination="/queue/demisto-test" body="send the message to queue"

Human Readable Output

Message sent to ActiveMQ destination: /topic/demisto-test with transaction ID: 69726a84-ee17-4db5-a6da-5171da9986d3

activemq-subscribe


Subscribes to and reads messages from a topic or queue. Must provide either queue-name or topic-name. You can’t provide both.

Base Command

activemq-subscribe

Input
Argument Name Description Required
subscription-id The subscription unique identifier. Required
topic-name The topic to subscribe to. Optional
queue-name The queue to subscribe to. Optional
Context Output

There is no context output for this command.

Command Example

!activemq-subscribe subscription-id=1 topic-name=demisto-test

Human Readable Output

send to topic message

Configuration parameters

  • hostname — Server IP Address (e.g., 192.168.0.1) (required)
  • port — Port
  • client-id — Client ID
  • credentials — ---------------------------- Basic Authentication ---------------------------- Username
  • client_cert — --------------------- Certificate Authentication --------------------- Client certificate (.pem)
  • client_key — Client certificate key (.key)
  • root_ca — Root Certificate
  • subscription-id — ---------------------------- Fetch Incidents ---------------------------- Subscription ID
  • isFetch — Fetch incidents
  • incidentType — Incident type
  • incidentFetchInterval — Incidents Fetch Interval
  • topic-name — Topic Name (for subscription)
  • queue_name — Queue Name (for subscription)

Commands (2)

  • activemq-send

    Sends a message to the specified destination.

  • activemq-subscribe

    Subscribes to and reads messages from a topic or queue. Must provide either queue-name or topic-name. You can't provide both.

import demistomock as demisto  # noqa: F401
from CommonServerPython import *  # noqa: F401
import os

import stomp


""" GLOBAL VARS """

HOSTNAME = demisto.params()["hostname"]
PORT = int(demisto.params().get("port") or 61613)
USERNAME = demisto.params().get("credentials", {}).get("identifier")
PASSWORD = demisto.params().get("credentials", {}).get("password")
CLIENT_CERT = demisto.params().get("client_cert")
CLIENT_KEY = demisto.params().get("client_key")
ROOT_CA = demisto.params().get("root_ca")


class MsgListener(stomp.ConnectionListener):
    def __init__(self):
        self.result_arr = []
        self.msg_ids = []

    def on_error(self, frame):
        demisto.results(f'received an error "{frame}"')

    def on_message(self, frame):
        self.result_arr.append(frame.body)
        self.msg_ids.append(frame.headers["message-id"])


""" HELPER FUNCTIONS """


def create_connection(client_cert, client_key, root_ca):
    client_path = None
    client_key_path = None
    if client_cert:
        client_path = "client.cert"
        with open(client_path, "wb") as file:
            file.write(client_cert)
            client_path = os.path.abspath(client_path)
    if client_key:
        client_key_path = "client_key.key"
        with open(client_key_path, "wb") as file:
            file.write(client_key)
    if root_ca:
        root_ca_path = "root_ca.key"
        with open(root_ca_path, "wb") as file:
            file.write(root_ca)

    conn = stomp.Connection([(HOSTNAME, PORT)])
    if client_cert or client_key or root_ca:
        demisto.debug("adding ssl certificate")
        conn.set_ssl(for_hosts=[(HOSTNAME, PORT)], key_file=client_key, cert_file=client_path)

    return conn


def connect(conn, client_id=None):
    if USERNAME or PASSWORD:
        if client_id and len(client_id) > 0:
            conn.connect(USERNAME, PASSWORD, wait=True, headers={"client-id": client_id})
        else:
            conn.connect(USERNAME, PASSWORD, wait=True)

    elif CLIENT_KEY or CLIENT_CERT or ROOT_CA:
        if client_id and len(client_id) > 0:
            conn.connect(wait=True)  # , headers = {'client-id': client_id })
        else:
            conn.connect(wait=True)
    else:
        raise ValueError("You must provide username/password or certificates")

    return conn


""" FUNCTIONS """


def send_message(conn):
    txid = conn.begin()
    dest = demisto.args()["destination"]
    body = demisto.args()["body"]

    if "headers" in demisto.args():
        try:
            headers_demisto = json.loads(demisto.args()["headers"])
        except Exception as e:
            demisto.error(f'Failed to parse "headers". Error: {e}')
            raise ValueError('Failed to parse "headers" argument to JSON. "headers"={}'.format(demisto.args()["headers"]))

        conn.send(dest, body, transaction=txid, headers=headers_demisto)
    else:
        conn.send(dest, body, transaction=txid)

    conn.commit(txid)
    demisto.results("Message sent to ActiveMQ destination: " + dest + " with transaction ID: " + txid)


def subscribe(client, conn, subscription_id, topic_name, queue_name):
    if not queue_name and not topic_name:
        raise ValueError("To subscribe you must provide either queue-name or topic-name")
    elif queue_name and topic_name:
        raise ValueError("Can't provide both queue-name and topic-name.")

    listener = MsgListener()
    if client and len(client) > 0:
        conn.set_listener("Demisto", listener)

    # ack='client-individual', headers={'activemq.subscriptionName': client})
    if queue_name:
        conn.subscribe("/queue/" + queue_name, subscription_id, ack="client-individual")
    elif topic_name:
        conn.subscribe(
            "/topic/" + topic_name, subscription_id, ack="client-individual", headers={"activemq.subscriptionName": client}
        )

    time.sleep(1)

    for msg in listener.result_arr:
        demisto.results(msg)

    for msg_id in listener.msg_ids:
        conn.ack(msg_id, subscription_id)


def fetch_incidents(client, conn, subscription_id, queue_name, topic_name):
    if not queue_name and not topic_name:
        raise ValueError("To fetch incidents you must provide either Queue Name or Topic Name")
    if queue_name and topic_name:
        raise ValueError("Can't provide both Queue Name and Topic name.")

    # conn = stomp.Connection(heartbeats=(4000, 4000))
    listener = MsgListener()
    if client and len(client) > 0:
        conn.set_listener("Demisto", listener)

    if queue_name:
        conn.subscribe("/queue/" + queue_name, subscription_id, ack="client-individual")
    else:
        conn.subscribe(
            "/topic/" + topic_name, subscription_id, ack="client-individual", headers={"activemq.subscriptionName": client}
        )

    incidents = []
    time.sleep(10)
    for i in range(len(listener.result_arr)):
        msg = listener.result_arr[i]
        msg_id = listener.msg_ids[i]
        incidents.append({"Name": "ActiveMQ incident:" + msg_id, "rawJSON": msg, "details": msg})
    demisto.incidents(incidents)

    for msg_id in listener.msg_ids:
        conn.ack(msg_id, subscription_id)


def main():
    client = demisto.params().get("client-id", "Demisto")

    conn = create_connection(client_cert=CLIENT_CERT, client_key=CLIENT_KEY, root_ca=ROOT_CA)

    LOG(f"command is {demisto.command()}")

    try:
        if demisto.command() == "test-module":
            # Test connectivity
            if demisto.params().get("isFetch"):
                queue_name = demisto.params().get("queue_name")
                topic_name = demisto.params().get("topic-name")

                if not queue_name and not topic_name:
                    raise ValueError("To fetch incidents you must provide either Queue Name or Topic Name")
                elif queue_name and topic_name:
                    raise ValueError("Can't provide both Queue Name and Topic name.")

            connect(conn)
            demisto.results("ok")

        elif demisto.command() == "activemq-send":
            connect(conn)
            send_message(conn)

        elif demisto.command() == "activemq-subscribe":
            subscription_id = demisto.args().get("subscription-id")
            topic_name = demisto.args().get("topic-name")
            queue_name = demisto.args().get("queue-name")

            connect(conn, client)
            subscribe(client, conn, subscription_id, topic_name, queue_name)

        elif demisto.command() == "fetch-incidents":
            subscription_id = demisto.params().get("subscription-id")
            queue_name = demisto.params().get("queue_name")
            topic_name = demisto.params().get("topic-name")

            connect(conn, client)
            fetch_incidents(client, conn, subscription_id, queue_name, topic_name)

    except Exception as e:
        if demisto.command() == "fetch-incidents":
            raise

        return_error(str(e))

    finally:
        conn.disconnect()


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