Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Empty file.
Empty file.
Binary file added Packs/SupernaZeroTrust/Author_image.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions Packs/SupernaZeroTrust/CONTRIBUTORS.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[
"Superna"
]
36 changes: 36 additions & 0 deletions Packs/SupernaZeroTrust/Integrations/SupernaZeroTrust/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
## Superna Zero Trust Integration

Integrates Cortex XSOAR with **Superna Zero Trust** to automate ransomware containment and recovery actions.

### Configure Superna Zero Trust on Cortex XSOAR

1. Go to **Settings → Integrations → Servers & Services**
2. Search for **Superna Zero Trust**
3. Click **Add instance**
4. Configure the following parameters:
- **API URL**: Base URL of your Superna Zero Trust / SERA server (e.g. `https://172.31.1.102`)
- **API Key**: API key stored securely using Cortex XSOAR credentials
- **Trust any certificate**: Enable only if using self-signed certificates
- **Use system proxy**: Optional

5. Click **Test** to validate connectivity

### Commands

| Command | Description |
|--------|-------------|
| `superna-zt-snapshot-critical-paths` | Snapshot Superna critical paths for ransomware recovery |
| `superna-zt-lockout-user` | Lock out a user from NAS storage access |
| `superna-zt-unlock-user` | Unlock a user from NAS storage access |

### Use Cases

- Ransomware containment
- Insider threat response
- Zero Trust enforcement
- NAS data protection

### Security Notes

- API keys are stored using Cortex XSOAR’s secure credentials store
- No secrets or IP addresses are embedded in playbooks
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
\
from typing import Any, Dict

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_cmd(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_cmd(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_cmd(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") # 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_cmd(client))
elif cmd == "superna-zt-lockout-user":
return_results(lockout_cmd(client, demisto.args()))
elif cmd == "superna-zt-unlock-user":
return_results(unlock_cmd(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()
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
commonfields:
id: SupernaZeroTrust
version: -1
name: SupernaZeroTrust
display: Superna Zero Trust
category: Utilities
description: Run Superna Zero Trust ransomware containment actions (critical path snapshot, user lockout/unlock) via the Superna API.
configuration:
- display: API URL (e.g. https://sera.example.local)
name: base_url
type: 0
required: true
- displaypassword: API Key
name: credentials
type: 9
required: true
hiddenusername: true
- display: Trust any certificate (not secure)
name: insecure
type: 8
required: false
defaultvalue: "false"
- display: Use system proxy settings
name: proxy
type: 8
required: false
defaultvalue: "false"
script:
script: "-"
type: python
subtype: python3
dockerimage: demisto/python3:3.10.13.86272
commands:
- name: superna-zt-snapshot-critical-paths
description: Create a snapshot of Superna critical paths for ransomware rapid recovery.
outputs:
- contextPath: SupernaZeroTrust.Snapshot.Result
description: API response from snapshot operation.
type: Unknown
- name: superna-zt-lockout-user
description: Lock out a user from NAS storage access.
arguments:
- name: username
required: true
description: Username to lock out.
outputs:
- contextPath: SupernaZeroTrust.Lockout.Result
description: API response from lockout operation.
type: Unknown
- name: superna-zt-unlock-user
description: Unlock a user from NAS storage access.
arguments:
- name: username
required: true
description: Username to unlock.
outputs:
- contextPath: SupernaZeroTrust.Unlock.Result
description: API response from unlock operation.
type: Unknown
fromversion: 6.10.0
tests:
- No tests
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
"""Unit tests for SupernaZeroTrust integration"""

import pytest
from SupernaZeroTrust import Client


def test_client_initialization():
"""Test that client initializes correctly"""
client = Client(
base_url='https://test.example.com',
verify=False,
proxy=False,
headers={'api_key': 'test-key'}
)
assert client._base_url == 'https://test.example.com/'


def test_snapshot_command(mocker):
"""Test snapshot-critical-paths command"""
from SupernaZeroTrust import snapshot_critical_paths_command

mock_client = mocker.Mock()
mock_client.snapshot_critical_paths.return_value = {'status': 'success'}

result = snapshot_critical_paths_command(mock_client)

assert result.outputs == {'status': 'success'}
assert 'SupernaZeroTrust.Snapshot.Result' in result.outputs_prefix


def test_lockout_command(mocker):
"""Test lockout-user command"""
from SupernaZeroTrust import lockout_user_command

mock_client = mocker.Mock()
mock_client.lockout_user.return_value = {'status': 'success'}

result = lockout_user_command(mock_client, {'username': 'testuser'})

assert result.outputs == {'status': 'success'}
assert 'SupernaZeroTrust.Lockout.Result' in result.outputs_prefix


def test_unlock_command(mocker):
"""Test unlock-user command"""
from SupernaZeroTrust import unlock_user_command

mock_client = mocker.Mock()
mock_client.unlock_user.return_value = {'status': 'success'}

result = unlock_user_command(mock_client, {'username': 'testuser'})

assert result.outputs == {'status': 'success'}
assert 'SupernaZeroTrust.Unlock.Result' in result.outputs_prefix
Loading