Syslog Sender

Use the Syslog Sender integration to send messages and mirror incident War Room entries to Syslog.

Analytics & SIEM · Syslog

Details

IDSyslog Sender
ProviderOpen Source
CategoryAnalytics & SIEM
From Version5.5.0
Docker Imagedemisto/syslog:1.0.0.10133006
Supported ModulesAgentix XSIAM

README

Overview


Use the Syslog Sender integration to send messages in RFC 5424 message format and mirror incident War Room entries to Syslog.

Use Cases


  • Send messages to Syslog via TCP or UDP or TLS.
  • Mirror incident war room entries to Syslog.
  • Track any activity from the Playground and War Room to your SIEM for improved visibility. This activity should be logged and attributed to the specific analyst.

Configure Syslog Sender on Cortex XSOAR


Usage example for rsyslog

To allow sending messages to rsyslog via Cortex XSOAR, the following lines have to be in the rsyslog configuration:

For TCP:

module(load="imtcp")
input(type="imtcp" port="<port>")

For UDP:

module(load="imudp")
input(type="imudp" port="<port>")

Usage example for sending War Room/Playground actions to Syslog

  1. From the Incidents page, click an incident.
  2. Run the !mirror-investigation type=”all” command.
    If you receive an Investication mirrored to Syslog successfully response, any action in the War Room will be sent to Syslog.

For example:
Run the command !Print value=”test msg”

<14>1 2023-09-19T13:49:38.140870+00:00 a1427a8493b5 SysLogLogger 1 - - 29, 105@29, admin:   !Print value=" incident owner is ${incident.owner}"
<14>1 2023-09-19T13:49:38.162145+00:00 a4140f2eb707 SysLogLogger 1 - - 29, 106@29, DBot:    incident owner is admin

Syslog already contains the analyst name - admin (the user who performed the action).
The action is: !Print value=”test msg”
The action result appears on the second line.

If you run the same command with a different user on the same Cortex XSOAR instance, the output will be:

<14>1 2023-09-19T13:56:02.152486+00:00 a1427a8493b5 SysLogLogger 1 - - 8069, 86@8069, jsmith:   !Print value=" incident owner is ${incident.owner}"
<14>1 2023-09-19T13:56:02.180858+00:00 a4140f2eb707 SysLogLogger 1 - - 8069, 87@8069, DBot:    incident owner is admin

Username (analyst) is present and located before each command. In this case, jsmith.
The timestamp is present and loacated at the beginning of each string.
To determine the execution time (duration), calculate the difference between the second timestamp and the first.

Integration configuration

  1. Navigate to Settings > Integrations > Servers & Services.
  2. Search for Syslog Sender.
  3. Click Add instance to create and configure a new integration instance.
    • Name: a textual name for the integration instance.
    • IP Address (e.g. 127.0.0.1)
    • Port
    • Protocol (TCP / UDP)
    • Minimum severity of incidents to send messages on
    • Log level to send
    • Facility
    • Long running instance. Required for investigation mirroring.
    • Incident type
  4. 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. mirror-investigation
  2. send-notification

1. mirror-investigation


Mirrors the investigation’s War Room to syslog.

Base Command

mirror-investigation

Input
Argument Name Description Required
type The mirroring type. Can be “all”, which mirrors everything, “chat”, which mirrors only chats (not commands), or “none”, which stops all mirroring. Optional
Context Output

There is no context output for this command.

Command Example

!mirror-investigation

Human Readable Output

Investigation mirrored successfully.

2. send-notification


Sends a message to syslog.

Base Command

send-notification

Input
Argument Name Description Required
message The message content. Optional
entry An entry ID to send as a link. Optional
ignoreAddURL Whether to include a URL to the relevant component in Cortex XSOAR. Can be “true” or “false”. The default value is “false’. Optional
level Log level to send. Can be “DEBUG”, “INFO”, “WARNING”, “ERROR”, or “CRITICAL”. Optional
Context Output

There is no context output for this command.

Command Example

!send-notification message=Test ignoreAddURL=true

Human Readable Output

Message sent to Syslog successfully.

3. syslog-send


Send a message to Syslog

Base Command

syslog-send

Input
Argument Name Description Required
message The message content. Optional
level The log level to send. Can be “DEBUG”, “INFO”, “WARNING”, “ERROR”, or “CRITICAL”. Optional
address The Syslog server address. Optional
protocol The protocol to use Optional
port The Syslog server port (required for TCP or UDP protocols). Optional
facility The Syslog facility. Optional
Context Output

There is no context output for this command.

Command Example

!syslog-send address=127.0.0.1 port=514 protocol=TCP message=yo level=ERROR

Human Readable Output

Message sent to Syslog successfully.

Troubleshooting


Make sure you can access the Syslog server on the provided IP address and the port is open.

Demo Video


Sorry, your browser doesn't support embedded videos. You can download the video at: https://github.com/demisto/content-assets/blob/7982404664dc68c2035b7c701d093ec026628802/Assets/Syslog/syslog-sender-demo.mp4

Configuration parameters

  • address — IP Address (e.g., 127.0.0.1)
  • port — Port
  • protocol — Protocol
  • certificate
  • self_signed_certificate — Self Signed Certificate
  • facility — Facility
  • priority — Log level to send
  • severity — Minimum severity of incidents to send messages on

Commands (3)

  • mirror-investigation

    Mirrors the investigation's War Room to Syslog.

  • send-notification

    Sends a message to Syslog. Used by the mirroring functionality.

  • syslog-send

    Sends a message to Syslog.

from CommonServerPython import *
import pytest
from contextlib import contextmanager
import logging


class Logger:
    def debug(self, message):
        return "debug" + message

    def info(self, message):
        return "info" + message

    def warning(self, message):
        return "warning" + message

    def error(self, message):
        return "error" + message

    def critical(self, message):
        return "critical" + message


class Manager:
    @contextmanager
    def get_logger(self):
        try:
            yield Logger()
        finally:
            pass


def test_init_manager():
    from SyslogSender import init_manager

    # Set
    params = {"address": "127.0.0.1", "port": "514", "protocol": "tcp", "priority": "LOG_DEBUG", "facility": "LOG_SYSLOG"}

    # Arrange
    manager = init_manager(params)

    # Assert
    assert manager.address == "127.0.0.1"
    assert manager.port == 514
    assert manager.protocol == "tcp"
    assert manager.logging_level == 10
    assert manager.facility == 5


@pytest.mark.parametrize("investigation_id", ["999", "909"])
def test_mirror_investigation_new_and_existing(mocker, investigation_id):
    from SyslogSender import mirror_investigation

    # Set

    mocker.patch.object(demisto, "args", return_value={})
    mocker.patch.object(demisto, "investigation", return_value={"id": investigation_id})
    mocker.patch.object(demisto, "results")
    mocker.patch.object(demisto, "mirrorInvestigation")

    # Arrange
    mirror_investigation()

    success_results = demisto.results.call_args_list[0][0]
    mirror_id = demisto.mirrorInvestigation.call_args[0][0]
    mirror_type = demisto.mirrorInvestigation.call_args[0][1]
    auto_close = demisto.mirrorInvestigation.call_args[0][2]

    # Assert
    assert success_results[0] == "Investigation mirrored to Syslog successfully."
    assert mirror_id == investigation_id
    assert mirror_type == "all:FromDemisto"
    assert auto_close is False


def test_send_with_severity(mocker):
    from SyslogSender import syslog_send_notification

    # Set
    mocker.patch.object(demisto, "args", return_value={"severity": "4", "message": "!!!", "messageType": "incidentOpened"})
    link = "https://www.eizelulz.com:8443/#/WarRoom/727"
    mocker.patch.object(demisto, "investigation", return_value={"type": 1, "id": 1})
    mocker.patch.object(demisto, "demistoUrls", return_value={"warRoom": link})
    mocker.patch.object(demisto, "results")
    mocker.patch.object(Logger, "info")

    # Arrange
    syslog_send_notification(Manager(), 1)
    send_args = Logger.info.call_args[0]
    results = demisto.results.call_args[0][0]

    # Assert
    assert send_args[0] == "1, !!! https://www.eizelulz.com:8443/#/WarRoom/727"
    assert results == "Message sent to Syslog successfully."


def test_send_with_severity_zero(mocker):
    from SyslogSender import syslog_send_notification

    # Set
    mocker.patch.object(demisto, "args", return_value={"severity": "0", "message": "!!!", "messageType": "incidentOpened"})
    link = "https://www.eizelulz.com:8443/#/WarRoom/727"
    mocker.patch.object(demisto, "investigation", return_value={"type": 1, "id": 1})
    mocker.patch.object(demisto, "demistoUrls", return_value={"warRoom": link})
    mocker.patch.object(demisto, "results")
    mocker.patch.object(Logger, "critical")

    # Arrange
    syslog_send_notification(Manager(), 1)
    send_count = Logger.critical.call_count
    results_count = demisto.results.call_count

    # Assert
    assert send_count == 0
    assert results_count == 0


def test_send(mocker):
    from SyslogSender import syslog_send_notification

    # Set
    mocker.patch.object(demisto, "args", return_value={"message": "eyy"})
    link = "https://www.eizelulz.com:8443/#/WarRoom/727"
    mocker.patch.object(demisto, "investigation", return_value={"type": 1, "id": 1})
    mocker.patch.object(demisto, "demistoUrls", return_value={"warRoom": link})
    mocker.patch.object(demisto, "results")
    mocker.patch.object(Logger, "info")

    # Arrange
    syslog_send_notification(Manager(), 1)
    send_args = Logger.info.call_args[0]
    results = demisto.results.call_args[0][0]

    # Assert
    assert send_args[0] == "1, eyy https://www.eizelulz.com:8443/#/WarRoom/727"
    assert results == "Message sent to Syslog successfully."


def test_send_with_non_default_log_level(mocker):
    from SyslogSender import syslog_send_notification

    # Set
    mocker.patch.object(demisto, "args", return_value={"message": "eyy", "level": "DEBUG"})
    link = "https://www.eizelulz.com:8443/#/WarRoom/727"
    mocker.patch.object(demisto, "investigation", return_value={"type": 1, "id": 1})
    mocker.patch.object(demisto, "demistoUrls", return_value={"warRoom": link})
    mocker.patch.object(demisto, "results")

    mocker.patch.object(Logger, "debug")
    mocker.patch.object(Logger, "info")  # This is the default log level

    # Arrange
    syslog_send_notification(Manager(), 1)
    debug_send_args = Logger.debug.call_args[0]
    info_send_args = Logger.info.call_args  # make sure nothing was sent in the info log level
    results = demisto.results.call_args[0][0]

    # Assert
    assert debug_send_args[0] == "1, eyy https://www.eizelulz.com:8443/#/WarRoom/727"
    assert not info_send_args
    assert results == "Message sent to Syslog successfully."


def test_prepare_certificate_file():
    """
    Given:
    - certificate: Certificate.
    When:
    - Preparing global variables and creating the StreamServer.

    Then:
    - Ensure globals are set as expected and server is returned with expected attributes.
    """
    from SyslogSender import prepare_certificate_file

    result = prepare_certificate_file("example")
    assert len(result)


def test_SyslogHandlerTLS_init(mocker):
    """
    Given:
    - address
    - port
    - facility
    - log_level
    - certificate: Certificate.
    When:
    - Preparing global variables and creating the SyslogHandlerTLS handler.

    Then:
    - Ensure globals are set as expected and the handler was created.
    """
    from SyslogSender import SyslogHandlerTLS

    address = "127.0.0.1"
    port = 6514
    log_level = logging.DEBUG
    facility = 0
    cert_path = "cert.pem"
    mocker.patch("ssl.SSLContext.load_verify_locations", return_value=None)
    mocker.patch.object(ssl.SSLContext, "wrap_socket")
    mocker.patch.object(socket.socket, "connect")
    handler = SyslogHandlerTLS(address, port, log_level, facility, cert_path, False)
    assert handler.address == address
    assert handler.port == port
    assert handler.certfile == cert_path
    assert handler.facility == facility
    assert handler.level == log_level


def test_SyslogManager():
    """
    Given:
    - address
    - port
    - facility
    - log_level
    - certificate: Certificate.
    When:
    - Preparing global variables and creating the SyslogHandlerTLS handler.

    Then:
    - Ensure globals are set as expected and the handler was created.
    """
    from SyslogSender import SyslogManager

    address = "127.0.0.1"
    port = 6514
    log_level = logging.DEBUG
    facility = 0
    cert_path = "cert.pem"
    protocol = "udp"
    self_signed = True
    handler = SyslogManager(address, port, protocol, log_level, facility, cert_path, self_signed)
    assert handler.address == address
    assert handler.port == port
    assert handler.syslog_cert_path == cert_path
    assert handler.facility == facility
    assert handler.logging_level == log_level


def test_syslog_send(mocker):
    """
    Given:
    - address
    - port
    - facility
    - log_level
    - certificate: Certificate.
    When:
    - calling syslog_send.

    Then:
    - Ensure the message was sent.
    """
    import SyslogSender

    mocker.patch.object(demisto, "args", return_value={})
    mocker.patch.object(SyslogSender, "send_log")
    demisto_results_mocker = mocker.patch.object(demisto, "results")
    SyslogSender.syslog_send(None)
    assert demisto_results_mocker.called
    assert demisto.results.call_args[0][0] == "Message sent to Syslog successfully."


def test_SyslogManager_tcp(mocker):
    """
    Given:
    - address
    - port
    - facility
    - log_level
    - certificate: Certificate.
    When:
    - calling creating a logger using tcp protocol.

    Then:
    - Ensure manger, handler and logger are being created.
    """
    from SyslogSender import SyslogManager, init_manager

    params = {
        "address": "127.0.0.1",
        "port": "514",
        "protocol": "tcp",
        "priority": "LOG_DEBUG",
        "facility": "LOG_SYSLOG",
        "cert_path": "",
    }
    handler = {
        "SysLogLogger": {
            "level": "INFO",
            "class": "rfc5424logging.handler.Rfc5424SysLogHandler",
            "address": ("127.0.0.1", 514),
            "enterprise_id": 32473,
        }
    }

    # Arrange
    manager = init_manager(params)
    mocker.patch.object(SyslogManager, "_get_handler", return_value=handler)
    handler = SyslogManager._get_handler(manager)
    # mocker.patch.object(Logger, 'setLevel')
    logger = SyslogManager._init_logger(manager, handler)
    assert logger.level == 10


def test_SyslogManager_tls(mocker):
    """
    Given:
    - address
    - port
    - facility
    - log_level
    - certificate: Certificate.
    When:
    - calling creating a logger using tls protocol.

    Then:
    - Ensure manger, handler and logger are being created.
    """
    import SyslogSender
    from SyslogSender import SyslogManager, init_manager

    params = {
        "address": "127.0.0.1",
        "port": "6514",
        "protocol": "tls",
        "priority": "LOG_DEBUG",
        "facility": "LOG_SYSLOG",
        "certificate": {"certificate": "cert.pem"},
    }
    handler = {
        "syslog": {
            "level": "INFO",
            "class": "tlssyslog.handlers.TLSSysLogHandler",
            "formatter": "simple",
            "address": ("127.0.0.1", 6514),
            "ssl_kwargs": {
                "cert_reqs": ssl.CERT_REQUIRED,
                "ssl_version": ssl.PROTOCOL_TLS_CLIENT,
                "ca_certs": "cert.pem",
            },
        }
    }

    # Arrange
    mocker.patch.object(SyslogSender, "prepare_certificate_file", return_value="cert.pem")
    manager = init_manager(params)
    mocker.patch.object(SyslogManager, "init_handler_tls", return_value=handler)
    handler = SyslogManager.init_handler_tls(manager, "cert.pem")
    logger = SyslogManager._init_logger(manager, handler)
    assert logger.level == 10


def test_main(mocker):
    import SyslogSender
    from SyslogSender import main

    params = {
        "address": "127.0.0.1",
        "port": "6514",
        "protocol": "tls",
        "priority": "LOG_DEBUG",
        "facility": "LOG_SYSLOG",
        "certificate": {"password": "-----BEGIN SSH CERTIFICATE----- MIIF7z gdwZcx IENpdH -----END SSH CERTIFICATE-----"},
    }
    mocker.patch.object(demisto, "params", return_value=params)
    mocker.patch.object(demisto, "command", return_value="syslog-send")
    mocker.patch.object(demisto, "args", return_value={})
    mocker.patch.object(SyslogSender, "send_log")
    demisto_results_mocker = mocker.patch.object(demisto, "results")
    main()
    assert demisto_results_mocker.called
    assert demisto.results.call_args[0][0] == "Message sent to Syslog successfully."