Acalvio ShadowPlex

Acalvio ShadowPlex is a comprehensive Autonomous Deception Platform that offers Advanced Threat Detection, Investigation and Response capabilities.

Deception & Breach Simulation · Acalvio ShadowPlex

Details

IDAcalvio ShadowPlex
ProviderAcalvio
CategoryDeception & Breach Simulation
From Version5.0.0
Docker Imagedemisto/python3:3.12.13.10116658
Supported ModulesAgentix XSIAM

README

Acalvio ShadowPlex is a comprehensive Autonomous Deception Platform that offers Advanced Threat Detection, Investigation and Response capabilities.
This integration was integrated and tested with Acalvio ShadowPlex 5.x and ShadowPlex API 2.0.

Configure Acalvio ShadowPlex in Cortex

Parameter Description Required
url Acalvio API Server URL (e.g. https://example.net) True
apikey Acalvio API Key True
insecure Trust SSL certificate False
proxy Use system proxy settings False

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.

acalvio-is-deception-host


Check if its a Deception Host

Base Command

acalvio-is-deception-host

Input

Argument Name Description Required
host Hostname or IP Address of Endpoint Required

Context Output

Path Type Description
Acalvio.IsDeceptionHost.is_deception Boolean Returns ‘True’ if Host is a Deception else ‘False’
Acalvio.IsDeceptionHost.host String Host to be checked if Deception

Command Example

!acalvio-is-deception-host host="10.10.10.10"

Context Example

{
    'is_deception': true, 
    'host': '10.10.10.10'
}

Human Readable Output

Results - Deception Host

Key Value
is_deception true
host 10.10.10.10

acalvio-is-deception-user


Check if its a Deception User

Base Command

acalvio-is-deception-user

Input

Argument Name Description Required
username Username of the Domain User Required
domain AD Domain Name to which User belongs to Optional

Context Output

Path Type Description
Acalvio.IsDeceptionUser.is_deception Boolean Returns ‘True’ if its a Deception User else ‘False’
Acalvio.IsDeceptionUser.username String Username to be checked if Deception
Acalvio.IsDeceptionUser.domain String Users Domain

Command Example

!acalvio-is-deception-user username="tom" domain="acalvio.com"

Context Example

{
    'is_deception': true, 
    'username': 'tom',
    'domain': 'acalvio.com'
}

Human Readable Output

Results - Deception User

| Key | Value |
| — | — |

is_deception true
username dmusernonadmin2
domain acalvio.com

acalvio-is-deception-file


Check if its a Deception File on the Endpoint

Base Command

acalvio-is-deception-file

Input

Argument Name Description Required
endpoint Hostname or IP Address of Endpoint where file resides Required
filename Name of the file to be checked Required

Context Output

Path Type Description
Acalvio.IsDeceptionFile.is_deception Boolean Returns ‘True’ if File is a Deception else ‘False’
Acalvio.IsDeceptionFile.filename String Filename to be checked if Deception
Acalvio.IsDeceptionFile.endpoint String Hostname or IP Address of Endpoint where file resides

Command Example

!acalvio-is-deception-file endpoint="win10-ep" filename="t33.pdf"

Context Example

{
    'is_deception': true, 
    'filename': 't33.pdf',
    'endpoint': 'win10-ep'
}

Human Readable Output

Results - Deception File

| Key | Value |
| — | — |

is_deception true
filename t33.pdf
endpoint win10-ep

acalvio-mute-deception-host


Mute a Deception Host

Base Command

acalvio-mute-deception-host

Input

Argument Name Description Required
host Deception Host to be Muted Required

Context Output

Path Type Description
Acalvio.MuteDeceptionHost.is_mute Boolean Returns ‘True’ if Deception is Muted else ‘False’
Acalvio.MuteDeceptionHost.host String Deception Host to be Muted

Command Example

acalvio-mute-deception-host host="win10-host"

Context Example

{
    'is_mute': true, 
    'host': 'win10-host'
}

Human Readable Output

Results - Mute Deception

| Key | Value |
| — | — |

is_mute true
host win10-host

acalvio-unmute-deception-host


Unmute a Deception Host

Base Command

acalvio-unmute-deception-host

Input

Argument Name Description Required
host Deception Host to be Unmuted Required

Context Output

Path Type Description
Acalvio.UnmuteDeceptionHost.is_unmute Boolean Returns ‘True’ if Deception is Unmuted else ‘False’
Acalvio.UnmuteDeceptionHost.host String Deception Host to be Unmuted

Command Example

acalvio-unmute-deception-host host="win10-host"

Context Example

{
    'is_unmute': true, 
    'host': 'win10-host'
}

Human Readable Output

Results - Unute Deception

| Key | Value |
| — | — |

is_unmute true
host win10-host

acalvio-mute-deception-on-endpoint


Mute a Deception on Endpoint

Base Command

acalvio-mute-deception-on-endpoint

Input

Argument Name Description Required
endpoint Hostname or IP Address of Endpoint Required

Context Output

Path Type Description
Acalvio.MuteDeceptionEndpoint.is_mute Boolean Returns ‘True’ if Deception is Muted else ‘False’
Acalvio.MuteDeceptionEndpoint.endpoint String Hostname or IP Address of Endpoint

Command Example

acalvio-mute-deception-on-endpoint endpoint="win10-ep"

Context Example

{
    'is_mute': true, 
    'endpoint': 'win10-ep'
}

Human Readable Output

Results - Mute Deception

| Key | Value |
| — | — |

is_mute true
endpoint win10-ep

acalvio-unmute-deception-on-endpoint


Unmute a Deception on Endpoint

Base Command

acalvio-unmute-deception-on-endpoint

Input

Argument Name Description Required
endpoint Hostname or IP Address of Endpoint Required

Context Output

Path Type Description
Acalvio.UnmuteDeceptionEndpoint.is_unmute Boolean Returns ‘True’ if Deception is Unmuted else ‘False’
Acalvio.UnmuteDeceptionEndpoint.endpoint String Hostname or IP Address of Endpoint

Command Example

acalvio-unmute-deception-on-endpoint endpoint="win10-ep"

Context Example

{
    'is_unmute': true, 
    'endpoint': 'win10-ep'
}

Human Readable Output

Results - Unmute Deception

| Key | Value |
| — | — |

is_unmute true
endpoint win10-ep

Configuration parameters

  • url — Acalvio API Server URL (e.g. https://example.net) (required)
  • apikey — Acalvio API Key (required)
  • insecure — Trust any certificate (not secure)
  • proxy — Use system proxy settings

Commands (7)

  • acalvio-is-deception-file

    Check for a Deception File on the Endpoint

  • acalvio-is-deception-host

    Check for a Deception Host

  • acalvio-is-deception-user

    Check for a Deception User

  • acalvio-mute-deception-host

    Mute a Deception Host

  • acalvio-mute-deception-on-endpoint

    Mute a Deception on Endpoint

  • acalvio-unmute-deception-host

    Unmute a Deception Host

  • acalvio-unmute-deception-on-endpoint

    Unmute a Deception on Endpoint

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

# Disable insecure warnings
urllib3.disable_warnings()

""" CONSTANTS """
OK_HTTP_CODES = (200, 201)


class Action:
    TEST_CONN = "ACTION_TEST_CONN"
    DECEPTION_FILE = "ACTION_DECEPTION_FILE"
    DECEPTION_HOST = "ACTION_DECEPTION_HOST"
    DECEPTION_USER = "ACTION_DECEPTION_USER"
    MUTE_DECEPTION_HOST = "ACTION_MUTE_DECEPTION_HOST"
    UNMUTE_DECEPTION_HOST = "ACTION_UNMUTE_DECEPTION_HOST"
    MUTE_DECEPTION_EP = "ACTION_MUTE_DECEPTION_EP"
    UNMUTE_DECEPTION_EP = "ACTION_UNMUTE_DECEPTION_EP"


# end of class - Action


class Uri:
    TEST_CONN = "/insights/test-connection"
    DECEPTION_FILE = "/insights/file"
    DECEPTION_HOST = "/insights/host"
    DECEPTION_USER = "/insights/user"
    MUTE_DECEPTION_HOST = "/insights/mute-decoy"
    UNMUTE_DECEPTION_HOST = "/insights/unmute-decoy"
    MUTE_DECEPTION_EP = "/insights/mute-host"
    UNMUTE_DECEPTION_EP = "/insights/unmute-host"


# end of class - Uri


class Client(BaseClient):
    """
    Client will implement the service API, and should not contain
    any Demisto logic.
    Should only do requests and return data.
    """

    def call_acal_api(self, **kwargs):
        """
        http request to Acalvio API server
        """

        _action = kwargs.get("action")

        _data = None
        _uri = ""
        _method = "POST"

        if _action == Action.TEST_CONN:
            _uri = Uri.TEST_CONN

        elif _action == Action.DECEPTION_FILE:
            _uri = Uri.DECEPTION_FILE
            _data = {"file": kwargs.get("filename"), "host": kwargs.get("endpoint")}

        elif _action == Action.DECEPTION_HOST:
            _uri = Uri.DECEPTION_HOST
            _data = {"host": kwargs.get("host")}

        elif _action == Action.DECEPTION_USER:
            _uri = Uri.DECEPTION_USER
            _data = {
                "user": kwargs.get("username"),
                "domain": kwargs.get("domain"),
            }

        elif _action == Action.MUTE_DECEPTION_HOST:
            _uri = Uri.MUTE_DECEPTION_HOST
            _data = {"host": kwargs.get("host")}

        elif _action == Action.UNMUTE_DECEPTION_HOST:
            _uri = Uri.UNMUTE_DECEPTION_HOST
            _data = {"host": kwargs.get("host")}

        elif _action == Action.MUTE_DECEPTION_EP:
            _uri = Uri.MUTE_DECEPTION_EP
            _data = {"host": kwargs.get("ep")}

        elif _action == Action.UNMUTE_DECEPTION_EP:
            _uri = Uri.UNMUTE_DECEPTION_EP
            _data = {"host": kwargs.get("ep")}

        res = self._http_request(
            method=_method,
            url_suffix=_uri,
            json_data=_data,
            resp_type="response",
            error_handler=get_api_error,
            ok_codes=OK_HTTP_CODES,
        )

        if _action != Action.TEST_CONN:
            demisto.info(
                f"Response from Acalvio API Server: "
                f"HTTP Status Code - {res.status_code}, "
                f"HTTP Reason - {res.reason}, HTTP Body - {res.text}"
            )

        return res.json()

    # end of function - call_acal_api


# end of class - Client


def get_api_error(res):
    message = "API - HTTP Response Error"
    error = ""
    outputs = None

    if res is not None:
        message = f"HTTP Status Code - {res.status_code}, HTTP Reason - {res.reason}, Message Body - {res.text}"
        outputs = {"error": True, "details": res.text}

    return_error(message=message, error=error, outputs=outputs)


# end of function - get_api_error


def do_test_connection(client):
    results = None

    res_json = client.call_acal_api(action=Action.TEST_CONN)

    if res_json is not None and "result" in res_json and type(res_json["result"]) is bool and res_json["result"]:
        results = "ok"  # Test Success

    else:
        return_error(message="Error in TestConnection")

    return results


# end of function - do_test_connection


def do_deception_host_command(client, args):
    results = None

    host = args.get("host")

    res_json = client.call_acal_api(action=Action.DECEPTION_HOST, host=host)

    if res_json is not None and "result" in res_json and type(res_json["result"]) is bool:
        out_result = {
            "IsDeception": res_json["result"],
            "Host": str(host),
            "DateTime": datetime.now().strftime("%Y-%m-%dT%H:%M:%S"),
        }

        results = CommandResults(
            outputs_prefix="Acalvio.IsDeceptionHost",
            outputs_key_field="Host",
            outputs=out_result,
            readable_output=tableToMarkdown("Acalvio ShadowPlex - Deception Host", out_result),
            raw_response=res_json,
        )
    else:
        return_error(message="Error in IsDeceptionHost")

    return results


# end of function - do_deception_host_command


def do_deception_file_command(client, args):
    results = None

    filename = args.get("filename")
    endpoint = args.get("endpoint")

    res_json = client.call_acal_api(action=Action.DECEPTION_FILE, filename=filename, endpoint=endpoint)

    if res_json is not None and "result" in res_json and type(res_json["result"]) is bool:
        out_result = {
            "IsDeception": res_json["result"],
            "Filename": str(filename),
            "Endpoint": str(endpoint),
            "DateTime": datetime.now().strftime("%Y-%m-%dT%H:%M:%S"),
        }

        results = CommandResults(
            outputs_prefix="Acalvio.IsDeceptionFile",
            outputs_key_field=["Filename", "Endpoint"],
            outputs=out_result,
            readable_output=tableToMarkdown("Acalvio ShadowPlex - Deception File", out_result),
            raw_response=res_json,
        )
    else:
        return_error(message="Error in IsDeceptionFile")

    return results


# end of function - do_deception_file_command


def do_deception_user_command(client, args):
    results = None

    username = args.get("username")
    domain = args.get("domain")

    res_json = client.call_acal_api(action=Action.DECEPTION_USER, username=username, domain=domain)

    if res_json is not None and "result" in res_json and type(res_json["result"]) is bool:
        out_result = {
            "IsDeception": res_json["result"],
            "Username": str(username),
            "Domain": str(domain) if domain is not None else None,
            "DateTime": datetime.now().strftime("%Y-%m-%dT%H:%M:%S"),
        }

        results = CommandResults(
            outputs_prefix="Acalvio.IsDeceptionUser",
            outputs_key_field=["Username", "Domain"],
            outputs=out_result,
            readable_output=tableToMarkdown("Acalvio ShadowPlex - Deception User", out_result),
            raw_response=res_json,
        )
    else:
        return_error(message="Error in IsDeceptionUser")

    return results


# end of function - do_deception_user_command


def do_mute_deception_host_command(client, args):
    results = None

    host = args.get("host")

    res_json = client.call_acal_api(action=Action.MUTE_DECEPTION_HOST, host=host)

    if res_json is not None and "rescode" in res_json:
        out_result = {
            "IsMute": res_json["rescode"] == 0,
            "Host": str(host),
            "DateTime": datetime.now().strftime("%Y-%m-%dT%H:%M:%S"),
        }

        results = CommandResults(
            outputs_prefix="Acalvio.MuteDeceptionHost",
            outputs_key_field="Host",
            outputs=out_result,
            readable_output=tableToMarkdown("Acalvio ShadowPlex - Mute Deception Host", out_result),
            raw_response=res_json,
        )
    else:
        return_error(message="Error in MuteDeceptionHost")

    return results


# end of function - do_mute_deception_host_command


def do_unmute_deception_host_command(client, args):
    results = None

    host = args.get("host")

    res_json = client.call_acal_api(action=Action.UNMUTE_DECEPTION_HOST, host=host)

    if res_json is not None and "rescode" in res_json:
        out_result = {
            "IsUnmute": res_json["rescode"] == 0,
            "Host": str(host),
            "DateTime": datetime.now().strftime("%Y-%m-%dT%H:%M:%S"),
        }

        results = CommandResults(
            outputs_prefix="Acalvio.UnmuteDeceptionHost",
            outputs_key_field="Host",
            outputs=out_result,
            readable_output=tableToMarkdown("Acalvio ShadowPlex - Unmute Deception Host", out_result),
            raw_response=res_json,
        )
    else:
        return_error(message="Error in UnmuteDeceptionHost")

    return results


# end of function - do_unmute_deception_host_command


def do_mute_deception_ep_command(client, args):
    results = None

    ep = args.get("endpoint")

    res_json = client.call_acal_api(action=Action.MUTE_DECEPTION_EP, ep=ep)

    if res_json is not None and "rescode" in res_json:
        out_result = {
            "IsMute": res_json["rescode"] == 0,
            "Endpoint": str(ep),
            "DateTime": datetime.now().strftime("%Y-%m-%dT%H:%M:%S"),
        }

        results = CommandResults(
            outputs_prefix="Acalvio.MuteDeceptionEndpoint",
            outputs_key_field="Endpoint",
            outputs=out_result,
            readable_output=tableToMarkdown("Acalvio ShadowPlex - Mute Deception on Endpoint", out_result),
            raw_response=res_json,
        )
    else:
        return_error(message="Error in MuteDeceptionEndpoint")

    return results


# end of function - do_mute_deception_ep_command


def do_unmute_deception_ep_command(client, args):
    results = None

    ep = args.get("endpoint")

    res_json = client.call_acal_api(action=Action.UNMUTE_DECEPTION_EP, ep=ep)

    if res_json is not None and "rescode" in res_json:
        out_result = {
            "IsUnmute": res_json["rescode"] == 0,
            "Endpoint": str(ep),
            "DateTime": datetime.now().strftime("%Y-%m-%dT%H:%M:%S"),
        }

        results = CommandResults(
            outputs_prefix="Acalvio.UnmuteDeceptionEndpoint",
            outputs_key_field="Endpoint",
            outputs=out_result,
            readable_output=tableToMarkdown("Acalvio ShadowPlex - Unmute Deception on Endpoint", out_result),
            raw_response=res_json,
        )
    else:
        return_error(message="Error in UnmuteDeceptionEndpoint")

    return results


# end of function - do_unmute_deception_ep_command


def main():
    """
    PARSE AND VALIDATE INTEGRATION PARAMS
    """

    params = demisto.params()

    # get Acalvio API Server url
    base_url = params["url"].rstrip("/")

    # get Acalvio API Key
    apikey = params["apikey"]

    # check if SSL is to be verified
    verify_certificate = not params.get("insecure", False)

    proxy = params.get("proxy", False)

    # set the headers
    headers = {"api_key": apikey, "content-type": "application/json"}

    demisto.info(f"Command being called is '{demisto.command()}'")
    result = None

    try:
        client = Client(base_url=base_url, verify=verify_certificate, headers=headers, proxy=proxy)

        if demisto.command() == "test-module":
            # This is the call made when pressing the integration Test button
            result = do_test_connection(client)

        elif demisto.command() == "acalvio-is-deception-host":
            result = do_deception_host_command(client, demisto.args())

        elif demisto.command() == "acalvio-is-deception-file":
            result = do_deception_file_command(client, demisto.args())

        elif demisto.command() == "acalvio-is-deception-user":
            result = do_deception_user_command(client, demisto.args())

        elif demisto.command() == "acalvio-mute-deception-host":
            result = do_mute_deception_host_command(client, demisto.args())

        elif demisto.command() == "acalvio-unmute-deception-host":
            result = do_unmute_deception_host_command(client, demisto.args())

        elif demisto.command() == "acalvio-mute-deception-on-endpoint":
            result = do_mute_deception_ep_command(client, demisto.args())

        elif demisto.command() == "acalvio-unmute-deception-on-endpoint":
            result = do_unmute_deception_ep_command(client, demisto.args())

        return_results(result)

    # Log exceptions
    except DemistoException as de:
        return_error(message=f"Failed to execute '{demisto.command()}' command. Error: {de!s}")


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