Esempio n. 1
0
class EventPublisher(DxlPublisherInterface):
    def __init__(self):
        self.client = None

    def connect(self, config_file="./dxlclient.config"):
        if self.isConnected():
            raise DxlJythonException(
                1100, "Already connected to the OpenDXL broker")

        try:
            logger.info("Reading configuration file from '%s'", config_file)
            config = DxlClientConfig.create_dxl_config_from_file(config_file)

            # Initialize DXL client using our configuration
            self.client = DxlClient(config)

            # Connect to DXL Broker
            self.client.connect()

            return
        except Exception as e:
            logger.info("Exception: " + e.message)
            raise DxlJythonException(
                1000, "Unable to establish a connection with the DXL broker")

    def sendMessage(self,
                    topic="/dsa/dxl/test/event2",
                    message="Default message"):
        if not self.isConnected():
            raise DxlJythonException(1200, "Not connected to a OpenDXL broker")

        try:
            event = Event(topic)

            # Encode string payload as UTF-8
            event.payload = message.encode()

            # Send event on DXL
            logger.info("Sending '" + message + "' to '" + topic + "'")
            self.client.send_event(event)

            return "Event successfully posted to topic '%s'" % topic

        except Exception as e:
            logger.info("Exception: " + e.message)
            raise DxlJythonException(
                1010, "Unable to communicate with a DXL broker")

    def disconnect(self):
        if not self.isConnected():
            return

        self.client.disconnect()

    def isConnected(self):
        if self.client is None:
            return False
        return self.client.connected
Esempio n. 2
0
class FunctionComponent(ResilientComponent):
    """Component that implements Resilient function 'mcafee_publish_to_dxl"""

    config_file = "dxlclient_config"

    def __init__(self, opts):
        """constructor provides access to the configuration options"""
        super(FunctionComponent, self).__init__(opts)
        try:
            self.config = opts.get("fn_mcafee_opendxl").get(self.config_file)
            if self.config is None:
                log.error(
                    self.config_file +
                    " is not set. You must set this path to run this function")
                raise ValueError(
                    self.config_file +
                    " is not set. You must set this path to run this function")

            # Create configuration from file for DxlClient
            config = DxlClientConfig.create_dxl_config_from_file(self.config)
            # Create client
            self.client = DxlClient(config)
            self.client.connect()
        except AttributeError:
            log.error(
                "There is no [fn_mcafee_opendxl] section in the config file,"
                "please set that by running resilient-circuits config -u")
            raise AttributeError(
                "[fn_mcafee_opendxl] section is not set in the config file")

    @handler("reload")
    def _reload(self, event, opts):
        """Configuration options have changed, save new values"""
        self.config = opts.get("fn_mcafee_opendxl").get(self.config_file)

    @function("mcafee_publish_to_dxl")
    def _mcafee_publish_to_dxl_function(self, event, *args, **kwargs):
        """Function: A function which takes 3 inputs:

        mcafee_topic_name: String of the topic name. ie: /mcafee/service/epo/remote/epo1.
        mcafee_dxl_payload: The text of the payload to publish to the topic.
        mcafee_return_request: Specify whether or not to wait for and return the response.


        The function will publish the provided payload to the provided topic.
        Indicate whether acknowledgment response should be returned."""
        try:
            yield StatusMessage("Starting...")
            # Get the function parameters:
            mcafee_topic_name = kwargs.get("mcafee_topic_name")  # text
            if not mcafee_topic_name:
                yield FunctionError("mcafee_topic_name is required")
            mcafee_dxl_payload = kwargs.get("mcafee_dxl_payload")  # text
            if not mcafee_dxl_payload:
                yield FunctionError("mcafee_dxl_payload is required")
            mcafee_publish_method = self.get_select_param(
                kwargs.get("mcafee_publish_method")
            )  # select, values: "Event", "Service"
            if not mcafee_publish_method:
                yield FunctionError("mcafee_publish_method is required")
            mcafee_wait_for_response = self.get_select_param(
                kwargs.get(
                    "mcafee_wait_for_response"))  # select, values: "Yes", "No"

            log.info("mcafee_topic_name: %s", mcafee_topic_name)
            log.info("mcafee_dxl_payload: %s", mcafee_dxl_payload)
            log.info("mcafee_publish_method: %s", mcafee_publish_method)
            log.info("mcafee_wait_for_response: %s", mcafee_wait_for_response)

            response = None

            # Publish Event
            if mcafee_publish_method == "Event":
                event = Event(mcafee_topic_name)
                event.payload = mcafee_dxl_payload
                yield StatusMessage("Publishing Event...")
                self.client.send_event(event)

            # Invoke Service
            else:
                req = Request(mcafee_topic_name)
                req.payload = mcafee_dxl_payload
                yield StatusMessage("Invoking Service...")

                if mcafee_wait_for_response == "No":
                    self.client.async_request(req)
                else:
                    response = Response(
                        self.client.sync_request(req, timeout=300))

            yield StatusMessage("Done...")
            r = {
                "mcafee_topic_name": mcafee_topic_name,
                "mcafee_dxl_payload": mcafee_dxl_payload,
                "mcafee_publish_method": mcafee_publish_method,
                "mcafee_wait_for_response": mcafee_wait_for_response
            }

            # Return response from publishing to topic
            if response is not None:
                r["response"] = vars(response)
                yield FunctionResult(r)
            else:
                yield FunctionResult(r)
        except Exception as e:
            yield FunctionError(e)
Esempio n. 3
0
class DXLBroker(object):
    class MyEventCallback(EventCallback):
        def __init__(self, broker):
            EventCallback.__init__(self)
            self.broker = broker

        def on_event(self, event):
            self.broker.logger.threaddebug(
                f"{self.broker.device.name}: Message {event.message_id} ({event.message_type}), received: {event.destination_topic}, payload: {event.payload}"
            )
            indigo.activePlugin.processReceivedMessage(self.broker.device.id,
                                                       event.destination_topic,
                                                       event.payload)

    def __init__(self, device):
        self.logger = logging.getLogger("Plugin.DXLBroker")
        self.deviceID = device.id

        address = device.pluginProps.get(u'address', "")
        port = device.pluginProps.get(u'port', "")
        ca_bundle = indigo.server.getInstallFolderPath(
        ) + '/' + device.pluginProps.get(u'ca_bundle', "")
        cert_file = indigo.server.getInstallFolderPath(
        ) + '/' + device.pluginProps.get(u'cert_file', "")
        private_key = indigo.server.getInstallFolderPath(
        ) + '/' + device.pluginProps.get(u'private_key', "")

        self.logger.debug(
            f"{device.name}: Broker __init__ address = {address}, ca_bundle = {ca_bundle}, cert_file = {cert_file}, private_key = {private_key}"
        )

        device.updateStateOnServer(key="status", value="Not Connected")
        device.updateStateImageOnServer(indigo.kStateImageSel.SensorOff)

        # Create the client configuration
        broker = Broker.parse(f"ssl://{address}:{port}")
        config = DxlClientConfig(broker_ca_bundle=ca_bundle,
                                 cert_file=cert_file,
                                 private_key=private_key,
                                 brokers=[broker])

        # Create the DXL client
        self.dxl_client = DxlClient(config)

        # Connect to the fabric
        self.dxl_client.connect()
        device.updateStateOnServer(key="status", value="Connected")
        device.updateStateImageOnServer(indigo.kStateImageSel.SensorOn)

        subs = device.pluginProps.get(u'subscriptions', None)
        if subs:
            for topic in subs:
                self.dxl_client.add_event_callback(topic,
                                                   self.MyEventCallback(self))
                self.logger.info(u"{}: Subscribing to: {}".format(
                    device.name, topic))

    def disconnect(self):
        device = indigo.devices[self.deviceID]
        self.dxl_client.disconnect()
        self.dxl_client.destroy()
        device.updateStateOnServer(key="status", value="Not Connected")
        device.updateStateImageOnServer(indigo.kStateImageSel.SensorOff)

    def publish(self, topic, payload=None, qos=0, retain=False):
        event = Event(topic)
        event.payload = payload
        self.dxl_client.send_event(event)

    def subscribe(self, topic):
        device = indigo.devices[self.deviceID]
        self.logger.info(f"{device.name}: Subscribing to: {topic}")
        self.dxl_client.add_event_callback(topic, self.MyEventCallback(self))

    def unsubscribe(self, topic):
        device = indigo.devices[self.deviceID]
        self.logger.info(f"{device.name}: Unsubscribing from: {topic}")
        self.dxl_client.unsubscribe(topic)
Esempio n. 4
0
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'