SupernaZeroTrust

Run Superna Zero Trust ransomware containment actions (critical path snapshot, user lockout/unlock) via the Superna API.

Utilities · Superna Zero Trust

Details

IDSupernaZeroTrust
CategoryUtilities
From Version8.9.0
Docker Imagedemisto/python3:3.12.13.10116658

README

Superna Zero Trust

Integrates Cortex XSOAR with Superna Zero Trust to automate ransomware containment and recovery actions via the Superna SERA API.

Configure Superna Zero Trust on Cortex XSOAR

  1. Navigate to Settings > Integrations > Servers & Services
  2. Search for Superna Zero Trust
  3. Click Add instance and configure the following parameters:
Parameter Description Required
API URL Base URL of your Superna Zero Trust / SERA server (e.g. https://sera.example.local) True
API Key API key for authenticating to the Superna SERA API True
Trust any certificate (not secure) Skip TLS certificate verification. Enable only for self-signed certificates. False
Use system proxy settings Route API calls through the system proxy False
  1. Click Test to validate connectivity.

Commands

superna-zt-snapshot-critical-paths

Create a snapshot of Superna critical paths for ransomware rapid recovery.

Base Command

superna-zt-snapshot-critical-paths

Input

There are no input arguments for this command.

Context Output

Path Type Description
SupernaZeroTrust.Snapshot.Status String Result status: Success or AlreadyExists
SupernaZeroTrust.Snapshot.Message String Human-readable result message
SupernaZeroTrust.Snapshot.Result Unknown Raw API response from the snapshot operation

Command Example

!superna-zt-snapshot-critical-paths

Human Readable Output

✅ Snapshot created successfully

superna-zt-lockout-user

Lock out a user from NAS storage access.

Base Command

superna-zt-lockout-user

Input

Argument Name Description Required
username The username to lock out from NAS storage access Required

Context Output

Path Type Description
SupernaZeroTrust.Lockout.Username String The username that was locked out
SupernaZeroTrust.Lockout.Result Unknown Raw API response from the lockout operation

Command Example

!superna-zt-lockout-user username="jsmith"

superna-zt-unlock-user

Unlock a user from NAS storage access.

Base Command

superna-zt-unlock-user

Input

Argument Name Description Required
username The username to unlock from NAS storage access Required

Context Output

Path Type Description
SupernaZeroTrust.Unlock.Username String The username that was unlocked
SupernaZeroTrust.Unlock.Result Unknown Raw API response from the unlock operation

Command Example

!superna-zt-unlock-user username="jsmith"

Configuration parameters

  • base_url — API URL (e.g. https://sera.example.local) (required)
  • credentials — (required)
  • insecure — Trust any certificate (not secure)
  • proxy — Use system proxy settings

Commands (3)

  • superna-zt-lockout-user

    Lock out a user from NAS storage access.

  • superna-zt-snapshot-critical-paths

    Create a snapshot of Superna critical paths for ransomware rapid recovery.

  • superna-zt-unlock-user

    Unlock a user from NAS storage access.

from typing import Any

import demistomock as demisto  # noqa: F401
from CommonServerPython import *  # noqa: F401,F403


class Client(BaseClient):
    def __init__(self, base_url: str, api_key: str, verify: bool, proxy: bool):
        headers = {
            "Accept": "application/json",
            "Content-Type": "application/json",
            "api_key": api_key,
        }
        super().__init__(base_url=base_url, verify=verify, proxy=proxy, headers=headers)

    def snapshot_critical_paths(self) -> dict[str, Any]:
        return self._http_request(
            method="POST",
            url_suffix="/sera/v2/ransomware/criticalpaths",
            json_data={},
        )

    def lockout_user(self, username: str) -> dict[str, Any]:
        return self._http_request(
            method="POST",
            url_suffix=f"/sera/v2/ransomware/lockout/{username}",
            json_data={},
        )

    def unlock_user(self, username: str) -> dict[str, Any]:
        return self._http_request(
            method="POST",
            url_suffix=f"/sera/v2/ransomware/unlock/{username}",
            json_data={},
        )

    def healthcheck(self) -> dict[str, Any]:
        return self._http_request(
            method="GET",
            url_suffix="/sera/v1/healthcheck",
        )


def test_module(client: Client) -> str:
    client.healthcheck()
    return "ok"


def snapshot_critical_paths_command(client: Client) -> CommandResults:
    try:
        res = client.snapshot_critical_paths()
        return CommandResults(
            outputs_prefix="SupernaZeroTrust.Snapshot",
            outputs={"Status": "Success", "Message": "Snapshot created successfully", "Result": res},
            readable_output="✅ Snapshot created successfully",
            raw_response=res,
        )
    except DemistoException as e:
        # Check if it's a 429 error (rate limit / recent snapshot exists)
        if "429" in str(e) or "Too Many Requests" in str(e):
            return CommandResults(
                outputs_prefix="SupernaZeroTrust.Snapshot",
                outputs={
                    "Status": "AlreadyExists",
                    "Message": "Snapshot already created within the last hour. Please wait before creating another snapshot.",
                },
                readable_output="⚠️ Snapshot already created within the last hour. Please wait before creating another snapshot.",
                raw_response={"error": str(e)},
            )
        else:
            # Re-raise other errors
            raise


def lockout_user_command(client: Client, args: dict[str, Any]) -> CommandResults:
    username = args.get("username")
    if not username:
        raise DemistoException("Missing required argument: username")
    res = client.lockout_user(username)
    return CommandResults(
        outputs_prefix="SupernaZeroTrust.Lockout",
        outputs={"Username": username, "Result": res},
        raw_response=res,
    )


def unlock_user_command(client: Client, args: dict[str, Any]) -> CommandResults:
    username = args.get("username")
    if not username:
        raise DemistoException("Missing required argument: username")
    res = client.unlock_user(username)
    return CommandResults(
        outputs_prefix="SupernaZeroTrust.Unlock",
        outputs={"Username": username, "Result": res},
        raw_response=res,
    )


def main():  # pragma: no cover
    params = demisto.params()
    base_url = (params.get("base_url") or "").rstrip("/")
    creds = params.get("credentials") or {}
    api_key = creds.get("password") or ""  # Authentication param: password holds the secret
    insecure = bool(params.get("insecure"))
    proxy = bool(params.get("proxy"))

    if not base_url:
        return_error("Missing required integration parameter: base_url")
    if not api_key:
        return_error("Missing required integration parameter: credentials (API key)")

    client = Client(base_url=base_url, api_key=api_key, verify=not insecure, proxy=proxy)

    try:
        cmd = demisto.command()
        if cmd == "test-module":
            return_results(test_module(client))
        elif cmd == "superna-zt-snapshot-critical-paths":
            return_results(snapshot_critical_paths_command(client))
        elif cmd == "superna-zt-lockout-user":
            return_results(lockout_user_command(client, demisto.args()))
        elif cmd == "superna-zt-unlock-user":
            return_results(unlock_user_command(client, demisto.args()))
        else:
            raise NotImplementedError(f"Command not implemented: {cmd}")
    except Exception as e:
        return_error(str(e), error=e)


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