xsoar-cli 1.0.9__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- xsoar_cli/__about__.py +4 -0
- xsoar_cli/__init__.py +1 -0
- xsoar_cli/case/README.md +57 -0
- xsoar_cli/case/__init__.py +0 -0
- xsoar_cli/case/commands.py +130 -0
- xsoar_cli/cli.py +41 -0
- xsoar_cli/config/README.md +64 -0
- xsoar_cli/config/__init__.py +0 -0
- xsoar_cli/config/commands.py +112 -0
- xsoar_cli/graph/README.md +17 -0
- xsoar_cli/graph/__init__.py +0 -0
- xsoar_cli/graph/commands.py +32 -0
- xsoar_cli/manifest/README.md +122 -0
- xsoar_cli/manifest/__init__.py +0 -0
- xsoar_cli/manifest/commands.py +271 -0
- xsoar_cli/pack/README.md +36 -0
- xsoar_cli/pack/__init__.py +0 -0
- xsoar_cli/pack/commands.py +59 -0
- xsoar_cli/playbook/README.md +43 -0
- xsoar_cli/playbook/__init__.py +0 -0
- xsoar_cli/playbook/commands.py +84 -0
- xsoar_cli/plugins/README.md +85 -0
- xsoar_cli/plugins/__init__.py +68 -0
- xsoar_cli/plugins/commands.py +273 -0
- xsoar_cli/plugins/manager.py +328 -0
- xsoar_cli/utilities.py +159 -0
- xsoar_cli-1.0.9.dist-info/METADATA +209 -0
- xsoar_cli-1.0.9.dist-info/RECORD +31 -0
- xsoar_cli-1.0.9.dist-info/WHEEL +4 -0
- xsoar_cli-1.0.9.dist-info/entry_points.txt +2 -0
- xsoar_cli-1.0.9.dist-info/licenses/LICENSE.txt +9 -0
xsoar_cli/__about__.py
ADDED
xsoar_cli/__init__.py
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
xsoar_cli/case/README.md
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# Case
|
|
2
|
+
|
|
3
|
+
Various case/incident related commands for XSOAR.
|
|
4
|
+
|
|
5
|
+
## Get
|
|
6
|
+
|
|
7
|
+
Retrieve basic information about a single case. Returns raw JSON formatted with 4-space indentation.
|
|
8
|
+
|
|
9
|
+
**Syntax:** `xsoar-cli case get [OPTIONS] CASENUMBER`
|
|
10
|
+
|
|
11
|
+
**Options:**
|
|
12
|
+
- `--environment TEXT` - Target environment (default: uses default environment from config)
|
|
13
|
+
|
|
14
|
+
**Examples:**
|
|
15
|
+
```
|
|
16
|
+
xsoar-cli case get 312412
|
|
17
|
+
xsoar-cli case get --environment prod 312412
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Clone
|
|
21
|
+
|
|
22
|
+
Clone a case from one environment to another. Useful for copying production cases to development environment for testing.
|
|
23
|
+
|
|
24
|
+
**Syntax:** `xsoar-cli case clone [OPTIONS] CASENUMBER`
|
|
25
|
+
|
|
26
|
+
**Options:**
|
|
27
|
+
- `--source TEXT` - Source environment (default: prod)
|
|
28
|
+
- `--dest TEXT` - Destination environment (default: dev)
|
|
29
|
+
|
|
30
|
+
**Examples:**
|
|
31
|
+
```
|
|
32
|
+
xsoar-cli case clone 312412 # Clone from prod to dev (defaults)
|
|
33
|
+
xsoar-cli case clone --source dev --dest prod 312412 # Clone from dev to prod
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Create
|
|
37
|
+
|
|
38
|
+
Create a new case in XSOAR with optional custom fields and case type.
|
|
39
|
+
|
|
40
|
+
**Syntax:** `xsoar-cli case create [OPTIONS] [NAME] [DETAILS]`
|
|
41
|
+
|
|
42
|
+
**Options:**
|
|
43
|
+
- `--environment TEXT` - Target environment (default: uses default environment from config)
|
|
44
|
+
- `--casetype TEXT` - Case type (default: uses default case type from config)
|
|
45
|
+
- `--custom-fields TEXT` - Additional fields in format "field1=value1,field2=value2" (useful when XSOAR has mandatory custom case fields configured)
|
|
46
|
+
- `--custom-fields-delimiter TEXT` - Delimiter for custom fields (default: ",")
|
|
47
|
+
|
|
48
|
+
**Arguments:**
|
|
49
|
+
- `NAME` - Case title (default: "Test case created from xsoar-cli")
|
|
50
|
+
- `DETAILS` - Case description (default: "Placeholder case details")
|
|
51
|
+
|
|
52
|
+
**Examples:**
|
|
53
|
+
```
|
|
54
|
+
xsoar-cli case create
|
|
55
|
+
xsoar-cli case create "Security Incident" "Suspicious network activity detected"
|
|
56
|
+
xsoar-cli case create --casetype "Phishing" --custom-fields "severity=High,source=Email" "Phishing Email" "Suspicious email received"
|
|
57
|
+
```
|
|
File without changes
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import json
|
|
2
|
+
from typing import TYPE_CHECKING
|
|
3
|
+
|
|
4
|
+
import click
|
|
5
|
+
|
|
6
|
+
from xsoar_cli.utilities import load_config, parse_string_to_dict, validate_environments
|
|
7
|
+
|
|
8
|
+
if TYPE_CHECKING:
|
|
9
|
+
from xsoar_client.xsoar_client import Client
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@click.group(help="Add new or modify existing XSOAR case")
|
|
13
|
+
def case() -> None:
|
|
14
|
+
pass
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@click.argument("casenumber", type=int)
|
|
18
|
+
@click.option("--environment", default=None, help="Default environment set in config file.")
|
|
19
|
+
@click.command(help="Get basic information about a single case in XSOAR")
|
|
20
|
+
@click.pass_context
|
|
21
|
+
@load_config
|
|
22
|
+
def get(ctx: click.Context, casenumber: int, environment: str | None) -> None:
|
|
23
|
+
if not environment:
|
|
24
|
+
environment = ctx.obj["default_environment"]
|
|
25
|
+
xsoar_client: Client = ctx.obj["server_envs"][environment]["xsoar_client"]
|
|
26
|
+
response = xsoar_client.get_case(casenumber)
|
|
27
|
+
if response["total"] == 0 and not response["data"]:
|
|
28
|
+
click.echo(f"Cannot find case ID {casenumber}")
|
|
29
|
+
ctx.exit(1)
|
|
30
|
+
click.echo(json.dumps(response, indent=4))
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
@click.argument("casenumber", type=int)
|
|
34
|
+
@click.option("--source", default="prod", show_default=True, help="Source environment")
|
|
35
|
+
@click.option("--dest", default="dev", show_default=True, help="Destination environment")
|
|
36
|
+
@click.option(
|
|
37
|
+
"--custom-fields",
|
|
38
|
+
default=None,
|
|
39
|
+
help='Additional fields on the form "myfield=my_value,anotherfield=another value". Use machine name for field names, e.g mycustomfieldname.',
|
|
40
|
+
)
|
|
41
|
+
@click.option("--custom-fields-delimiter", default=",", help='Delimiter when specifying additional fields. Default is ","')
|
|
42
|
+
@click.command()
|
|
43
|
+
@click.pass_context
|
|
44
|
+
@load_config
|
|
45
|
+
def clone( # noqa: PLR0913
|
|
46
|
+
ctx: click.Context,
|
|
47
|
+
casenumber: int,
|
|
48
|
+
source: str,
|
|
49
|
+
dest: str,
|
|
50
|
+
custom_fields: str | None,
|
|
51
|
+
custom_fields_delimiter: str,
|
|
52
|
+
) -> None:
|
|
53
|
+
"""Clones a case from source to destination environment."""
|
|
54
|
+
valid_envs = validate_environments(source, dest, ctx=ctx)
|
|
55
|
+
if not valid_envs:
|
|
56
|
+
click.echo(f"Error: cannot find environments {source} and/or {dest} in config")
|
|
57
|
+
ctx.exit(1)
|
|
58
|
+
if custom_fields and "=" not in custom_fields:
|
|
59
|
+
click.echo('Malformed custom fields. Must be on the form "myfield=myvalue"')
|
|
60
|
+
ctx.exit(1)
|
|
61
|
+
xsoar_source_client: Client = ctx.obj["server_envs"][source]["xsoar_client"]
|
|
62
|
+
results = xsoar_source_client.get_case(casenumber)
|
|
63
|
+
data = results["data"][0]
|
|
64
|
+
# Dbot mirror info is irrelevant. This will be added again if applicable by XSOAR after ticket creation in dev.
|
|
65
|
+
data.pop("dbotMirrorId")
|
|
66
|
+
data.pop("dbotMirrorInstance")
|
|
67
|
+
data.pop("dbotMirrorDirection")
|
|
68
|
+
data.pop("dbotDirtyFields")
|
|
69
|
+
data.pop("dbotCurrentDirtyFields")
|
|
70
|
+
data.pop("dbotMirrorTags")
|
|
71
|
+
data.pop("dbotMirrorLastSync")
|
|
72
|
+
data.pop("id")
|
|
73
|
+
data.pop("created")
|
|
74
|
+
data.pop("modified")
|
|
75
|
+
# Ensure that playbooks run immediately when the case is created
|
|
76
|
+
data["createInvestigation"] = True
|
|
77
|
+
if "CustomFields" in data:
|
|
78
|
+
data["CustomFields"] = data["CustomFields"] | parse_string_to_dict(custom_fields, custom_fields_delimiter)
|
|
79
|
+
|
|
80
|
+
xsoar_dest_client: Client = ctx.obj["server_envs"][dest]["xsoar_client"]
|
|
81
|
+
case_data = xsoar_dest_client.create_case(data=data)
|
|
82
|
+
click.echo(json.dumps(case_data, indent=4))
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
@click.option("--environment", default=None, help="Default environment set in config file.")
|
|
86
|
+
@click.option("--casetype", default="", show_default=True, help="Create case of specified type. Default type set in config file.")
|
|
87
|
+
@click.option(
|
|
88
|
+
"--custom-fields",
|
|
89
|
+
default=None,
|
|
90
|
+
help='Additional fields on the form "myfield=my_value,anotherfield=another value". Use machine name for field names, e.g mycustomfieldname.',
|
|
91
|
+
)
|
|
92
|
+
@click.option("--custom-fields-delimiter", default=",", help='Delimiter when specifying additional fields. Default is ","')
|
|
93
|
+
@click.argument("details", type=str, default="Placeholder case details")
|
|
94
|
+
@click.argument("name", type=str, default="Test case created from xsoar-cli")
|
|
95
|
+
@click.command()
|
|
96
|
+
@click.pass_context
|
|
97
|
+
@load_config
|
|
98
|
+
def create( # noqa: PLR0913
|
|
99
|
+
ctx: click.Context,
|
|
100
|
+
environment: str | None,
|
|
101
|
+
casetype: str,
|
|
102
|
+
name: str,
|
|
103
|
+
custom_fields: str | None,
|
|
104
|
+
custom_fields_delimiter: str,
|
|
105
|
+
details: str,
|
|
106
|
+
) -> None:
|
|
107
|
+
"""Creates a new case in XSOAR. If invalid case type is specified as a command option, XSOAR will default to using Unclassified."""
|
|
108
|
+
if custom_fields and "=" not in custom_fields:
|
|
109
|
+
click.echo('Malformed custom fields. Must be on the form "myfield=myvalue"')
|
|
110
|
+
ctx.exit(1)
|
|
111
|
+
if not environment:
|
|
112
|
+
environment = ctx.obj["default_environment"]
|
|
113
|
+
xsoar_client: Client = ctx.obj["server_envs"][environment]["xsoar_client"]
|
|
114
|
+
if not casetype:
|
|
115
|
+
casetype = ctx.obj["default_new_case_type"]
|
|
116
|
+
data = {
|
|
117
|
+
"createInvestigation": True,
|
|
118
|
+
"name": name,
|
|
119
|
+
"type": casetype,
|
|
120
|
+
"details": details,
|
|
121
|
+
"CustomFields": parse_string_to_dict(custom_fields, custom_fields_delimiter),
|
|
122
|
+
}
|
|
123
|
+
case_data = xsoar_client.create_case(data=data)
|
|
124
|
+
case_id = case_data["id"]
|
|
125
|
+
click.echo(f"Created XSOAR case {case_id}")
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
case.add_command(get)
|
|
129
|
+
case.add_command(clone)
|
|
130
|
+
case.add_command(create)
|
xsoar_cli/cli.py
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
|
|
3
|
+
import click
|
|
4
|
+
|
|
5
|
+
from .__about__ import __version__
|
|
6
|
+
from .case import commands as case_commands
|
|
7
|
+
from .config import commands as config_commands
|
|
8
|
+
from .graph import commands as graph_commands
|
|
9
|
+
from .manifest import commands as manifest_commands
|
|
10
|
+
from .pack import commands as pack_commands
|
|
11
|
+
from .playbook import commands as playbook_commands
|
|
12
|
+
from .plugins import commands as plugin_commands
|
|
13
|
+
from .plugins.manager import PluginManager
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@click.group()
|
|
17
|
+
@click.pass_context
|
|
18
|
+
@click.version_option(__version__)
|
|
19
|
+
@click.option("--debug", is_flag=True, help="Enable debug logging")
|
|
20
|
+
def cli(ctx: click.Context, debug: bool) -> None:
|
|
21
|
+
"""XSOAR CLI - Command line interface for XSOAR operations."""
|
|
22
|
+
if debug:
|
|
23
|
+
logging.basicConfig(level=logging.DEBUG)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
cli.add_command(config_commands.config)
|
|
27
|
+
cli.add_command(case_commands.case)
|
|
28
|
+
cli.add_command(pack_commands.pack)
|
|
29
|
+
cli.add_command(manifest_commands.manifest)
|
|
30
|
+
cli.add_command(playbook_commands.playbook)
|
|
31
|
+
cli.add_command(graph_commands.graph)
|
|
32
|
+
cli.add_command(plugin_commands.plugins)
|
|
33
|
+
|
|
34
|
+
# Load and register plugins after all core commands are added
|
|
35
|
+
plugin_manager = PluginManager()
|
|
36
|
+
try:
|
|
37
|
+
plugin_manager.load_all_plugins(ignore_errors=True)
|
|
38
|
+
plugin_manager.register_plugin_commands(cli)
|
|
39
|
+
except Exception:
|
|
40
|
+
# Silently ignore plugin loading errors to not break the CLI
|
|
41
|
+
pass
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# Config
|
|
2
|
+
|
|
3
|
+
Configuration management commands for XSOAR CLI.
|
|
4
|
+
|
|
5
|
+
## Create
|
|
6
|
+
|
|
7
|
+
Create a new configuration file based on a template. If the configuration file already exists, prompts for confirmation to overwrite.
|
|
8
|
+
|
|
9
|
+
**Syntax:** `xsoar-cli config create`
|
|
10
|
+
|
|
11
|
+
**Examples:**
|
|
12
|
+
```
|
|
13
|
+
xsoar-cli config create
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Show
|
|
17
|
+
|
|
18
|
+
Display the current configuration file contents as formatted JSON. API keys are masked by default for security.
|
|
19
|
+
|
|
20
|
+
**Syntax:** `xsoar-cli config show [OPTIONS]`
|
|
21
|
+
|
|
22
|
+
**Options:**
|
|
23
|
+
- `--unmask` - Show unmasked API keys in output
|
|
24
|
+
|
|
25
|
+
**Examples:**
|
|
26
|
+
```
|
|
27
|
+
xsoar-cli config show
|
|
28
|
+
xsoar-cli config show --unmask
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Validate
|
|
32
|
+
|
|
33
|
+
Validate that the configuration file is properly formatted JSON and test connectivity to each XSOAR environment defined in the configuration.
|
|
34
|
+
|
|
35
|
+
**Syntax:** `xsoar-cli config validate [OPTIONS]`
|
|
36
|
+
|
|
37
|
+
**Options:**
|
|
38
|
+
- `--only-test-environment TEXT` - Test connectivity for only the specified environment
|
|
39
|
+
|
|
40
|
+
**Examples:**
|
|
41
|
+
```
|
|
42
|
+
xsoar-cli config validate
|
|
43
|
+
xsoar-cli config validate --only-test-environment prod
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Set Credentials
|
|
47
|
+
|
|
48
|
+
Update API credentials for a specific environment in the configuration file. Automatically sets server version based on whether a key ID is provided.
|
|
49
|
+
|
|
50
|
+
**Syntax:** `xsoar-cli config set-credentials [OPTIONS] APITOKEN`
|
|
51
|
+
|
|
52
|
+
**Options:**
|
|
53
|
+
- `--environment TEXT` - Target environment (default: dev)
|
|
54
|
+
- `--key_id INTEGER` - API key ID for XSOAR 8 (sets server_version to 8, omit for XSOAR 6)
|
|
55
|
+
|
|
56
|
+
**Arguments:**
|
|
57
|
+
- `APITOKEN` - The API token to set for the environment
|
|
58
|
+
|
|
59
|
+
**Examples:**
|
|
60
|
+
```
|
|
61
|
+
xsoar-cli config set-credentials your-api-token-here
|
|
62
|
+
xsoar-cli config set-credentials --environment prod your-api-token-here
|
|
63
|
+
xsoar-cli config set-credentials --environment prod --key_id 123 your-api-token-here
|
|
64
|
+
```
|
|
File without changes
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import json
|
|
2
|
+
from typing import TYPE_CHECKING
|
|
3
|
+
|
|
4
|
+
import click
|
|
5
|
+
|
|
6
|
+
if TYPE_CHECKING:
|
|
7
|
+
from xsoar_client.xsoar_client import Client
|
|
8
|
+
|
|
9
|
+
import contextlib
|
|
10
|
+
|
|
11
|
+
from xsoar_cli.utilities import (
|
|
12
|
+
get_config_file_contents,
|
|
13
|
+
get_config_file_path,
|
|
14
|
+
get_config_file_template_contents,
|
|
15
|
+
load_config,
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
@click.group(help="Create/validate etc")
|
|
20
|
+
def config() -> None:
|
|
21
|
+
pass
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
@click.command()
|
|
25
|
+
@click.option("--unmask", "masked", is_flag=True, default=False)
|
|
26
|
+
@click.pass_context
|
|
27
|
+
@load_config
|
|
28
|
+
def show(ctx: click.Context, masked: bool) -> None:
|
|
29
|
+
"""Prints out current config. API keys are masked."""
|
|
30
|
+
config_file = get_config_file_path()
|
|
31
|
+
config = get_config_file_contents(config_file)
|
|
32
|
+
if not masked:
|
|
33
|
+
for key in config["server_config"]:
|
|
34
|
+
config["server_config"][key]["api_token"] = "MASKED" # noqa: S105
|
|
35
|
+
if "azure_storage_access_token" in config["server_config"][key]:
|
|
36
|
+
config["server_config"][key]["azure_storage_access_token"] = "*****" # noqa: S105
|
|
37
|
+
|
|
38
|
+
print(json.dumps(config, indent=4))
|
|
39
|
+
ctx.exit()
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
@click.command()
|
|
43
|
+
@click.option("--only-test-environment", default=None, show_default=True, help="Environment as defined in config file")
|
|
44
|
+
@click.option("--stacktrace", is_flag=True, default=False, help="Print full stack trace on config validation failure.")
|
|
45
|
+
@click.pass_context
|
|
46
|
+
@load_config
|
|
47
|
+
def validate(ctx: click.Context, only_test_environment: str, stacktrace: bool) -> None:
|
|
48
|
+
"""Validates that the configuration file is JSON and tests connectivity for each XSOAR Client environment defined."""
|
|
49
|
+
return_code = 0
|
|
50
|
+
for server_env in ctx.obj["server_envs"]:
|
|
51
|
+
if only_test_environment and server_env != only_test_environment:
|
|
52
|
+
# Ignore environment if --only-test-environment option is given and environment does not match
|
|
53
|
+
# what the user specified in option
|
|
54
|
+
continue
|
|
55
|
+
click.echo(f'Testing "{server_env}" environment...', nl=False)
|
|
56
|
+
xsoar_client: Client = ctx.obj["server_envs"][server_env]["xsoar_client"]
|
|
57
|
+
try:
|
|
58
|
+
xsoar_client.test_connectivity()
|
|
59
|
+
except ConnectionError as ex:
|
|
60
|
+
if stacktrace:
|
|
61
|
+
raise ConnectionError from ex
|
|
62
|
+
click.echo("FAILED")
|
|
63
|
+
return_code = 1
|
|
64
|
+
continue
|
|
65
|
+
click.echo("OK")
|
|
66
|
+
if ctx.obj["default_environment"] not in ctx.obj["server_envs"]:
|
|
67
|
+
click.echo(f'Error: default environment "{ctx.obj["default_environment"]}" not found in server config.')
|
|
68
|
+
return_code = 1
|
|
69
|
+
ctx.exit(return_code)
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
@click.command()
|
|
73
|
+
def create() -> None:
|
|
74
|
+
"""Create a new configuration file based on a template."""
|
|
75
|
+
# if confdir does not exist, create it
|
|
76
|
+
# if conf file does not exist, create it
|
|
77
|
+
config_file = get_config_file_path()
|
|
78
|
+
if config_file.is_file():
|
|
79
|
+
click.confirm(f"WARNING: {config_file} already exists. Overwrite?", abort=True)
|
|
80
|
+
config_file.parent.mkdir(exist_ok=True, parents=True)
|
|
81
|
+
config_data = get_config_file_template_contents()
|
|
82
|
+
config_file.write_text(json.dumps(config_data, indent=4))
|
|
83
|
+
click.echo(f"Wrote template configuration file {config_file}")
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
@click.option("--environment", default="dev", show_default=True, help="Environment as defined in config file")
|
|
87
|
+
@click.option("--key_id", type=int, help="If set then server config for server_version will be set to 8.")
|
|
88
|
+
@click.argument("apitoken", type=str)
|
|
89
|
+
@click.command()
|
|
90
|
+
@click.pass_context
|
|
91
|
+
@load_config
|
|
92
|
+
def set_credentials(ctx: click.Context, environment: str, apitoken: str, key_id: int) -> None: # noqa: ARG001
|
|
93
|
+
"""Set individual credentials for an environment in the config file."""
|
|
94
|
+
config_file = get_config_file_path()
|
|
95
|
+
config_data = json.loads(config_file.read_text())
|
|
96
|
+
config_data["server_config"][environment]["api_token"] = apitoken
|
|
97
|
+
# If we are given an API key ID, then we know it's supposed to be used in XSOAR 8.
|
|
98
|
+
# Set or remove the xsiam_auth_id accordingly.
|
|
99
|
+
if key_id:
|
|
100
|
+
config_data["server_config"][environment]["xsiam_auth_id"] = key_id
|
|
101
|
+
config_data["server_config"][environment]["server_version"] = 8
|
|
102
|
+
else:
|
|
103
|
+
config_data["server_config"][environment]["server_version"] = 6
|
|
104
|
+
with contextlib.suppress(KeyError):
|
|
105
|
+
config_data["server_config"][environment].pop("xsiam_auth_id")
|
|
106
|
+
config_file.write_text(json.dumps(config_data, indent=4))
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
config.add_command(create)
|
|
110
|
+
config.add_command(validate)
|
|
111
|
+
config.add_command(show)
|
|
112
|
+
config.add_command(set_credentials)
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# Graph
|
|
2
|
+
BETA command. Under active development.
|
|
3
|
+
|
|
4
|
+
## Generate
|
|
5
|
+
Creates a graph representation of the entire content repository and plots connected components. The syntax is `xsoar-cli graph generate [OPTIONS] [PACKS]...`
|
|
6
|
+
where the only required option is the path to the content repository. An optional PACKS argument can be specified with the paths of one or more content packs
|
|
7
|
+
you want to be plotted.
|
|
8
|
+
|
|
9
|
+
### Example invocations
|
|
10
|
+
```
|
|
11
|
+
# Plot the connected components from the graph of the entire content repository
|
|
12
|
+
xsoar-cli graph generate -rp ./content_repo
|
|
13
|
+
# Plot only the components found in MyFirstPack
|
|
14
|
+
xsoar-cli graph generate -rp ./content_repo ./content_repo/Packs/MyFirstPack
|
|
15
|
+
# Plot only connected components from MyFirstPack and MySecondPack
|
|
16
|
+
xsoar-cli graph generate -rp ./content_repo ./content_repo/Packs/MyFirstPack ./content_repo/Packs/MySecondPack
|
|
17
|
+
```
|
|
File without changes
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
|
|
3
|
+
import click
|
|
4
|
+
from xsoar_dependency_graph.xsoar_dependency_graph import ContentGraph
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
@click.group(help="(BETA) Create dependency graphs from one or more content packs")
|
|
8
|
+
def graph() -> None:
|
|
9
|
+
pass
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@click.option("-rp", "--repo-path", required=True, type=click.Path(exists=True), help="Path to content repository")
|
|
13
|
+
@click.argument("packs", nargs=-1, required=False, type=click.Path(exists=True))
|
|
14
|
+
@click.command()
|
|
15
|
+
def generate(packs: tuple[Path], repo_path: Path) -> None:
|
|
16
|
+
"""BETA
|
|
17
|
+
|
|
18
|
+
Generates a XSOAR dependency graph for one or more content packs. If no packs are defined in the [PACKS] argument,
|
|
19
|
+
a dependency graph is created for all content packs in the content repository.
|
|
20
|
+
|
|
21
|
+
Usage examples:
|
|
22
|
+
|
|
23
|
+
xsoar-cli graph generate -rp . Packs/Pack_one Packs/Pack_two
|
|
24
|
+
|
|
25
|
+
xsoar-cli graph generate -rp ."""
|
|
26
|
+
cg: ContentGraph = ContentGraph(repo_path=Path(repo_path))
|
|
27
|
+
packs_list = [Path(item) for item in packs]
|
|
28
|
+
cg.create_content_graph(pack_paths=packs_list)
|
|
29
|
+
cg.plot_connected_components()
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
graph.add_command(generate)
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
# Manifest
|
|
2
|
+
|
|
3
|
+
Content pack deployment management commands using a declarative configuration file (`xsoar_config.json`).
|
|
4
|
+
|
|
5
|
+
## Generate
|
|
6
|
+
|
|
7
|
+
Generate a new manifest file from currently installed content packs. Assumes all packs are marketplace packs (no custom packs).
|
|
8
|
+
|
|
9
|
+
**Syntax:** `xsoar-cli manifest generate [OPTIONS] MANIFEST_PATH`
|
|
10
|
+
|
|
11
|
+
**Options:**
|
|
12
|
+
- `--environment TEXT` - Target environment (default: uses default environment from config)
|
|
13
|
+
|
|
14
|
+
**Arguments:**
|
|
15
|
+
- `MANIFEST_PATH` - Path where the new manifest file will be created
|
|
16
|
+
|
|
17
|
+
**Examples:**
|
|
18
|
+
```
|
|
19
|
+
xsoar-cli manifest generate ./xsoar_config.json
|
|
20
|
+
xsoar-cli manifest generate --environment prod ./xsoar_config.json
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Validate
|
|
24
|
+
|
|
25
|
+
Validate manifest JSON syntax and verify all specified content packs are available. Tests connectivity to pack sources and checks local pack metadata for development packs.
|
|
26
|
+
|
|
27
|
+
**Syntax:** `xsoar-cli manifest validate [OPTIONS] MANIFEST_PATH`
|
|
28
|
+
|
|
29
|
+
**Options:**
|
|
30
|
+
- `--environment TEXT` - Target environment (default: uses default environment from config)
|
|
31
|
+
|
|
32
|
+
**Arguments:**
|
|
33
|
+
- `MANIFEST_PATH` - Path to the manifest file to validate
|
|
34
|
+
|
|
35
|
+
**Examples:**
|
|
36
|
+
```
|
|
37
|
+
xsoar-cli manifest validate ./xsoar_config.json
|
|
38
|
+
xsoar-cli manifest validate --environment staging ./xsoar_config.json
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Update
|
|
42
|
+
|
|
43
|
+
Compare installed packs against available versions and update the manifest file with latest versions. Prompts for confirmation on each upgrade.
|
|
44
|
+
|
|
45
|
+
**Syntax:** `xsoar-cli manifest update [OPTIONS] MANIFEST_PATH`
|
|
46
|
+
|
|
47
|
+
**Options:**
|
|
48
|
+
- `--environment TEXT` - Target environment (default: uses default environment from config)
|
|
49
|
+
|
|
50
|
+
**Arguments:**
|
|
51
|
+
- `MANIFEST_PATH` - Path to the manifest file to update
|
|
52
|
+
|
|
53
|
+
**Examples:**
|
|
54
|
+
```
|
|
55
|
+
xsoar-cli manifest update ./xsoar_config.json
|
|
56
|
+
xsoar-cli manifest update --environment dev ./xsoar_config.json
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Diff
|
|
60
|
+
|
|
61
|
+
Compare the manifest definition against what is actually installed on the XSOAR server. Shows packs that are missing or have version mismatches.
|
|
62
|
+
|
|
63
|
+
**Syntax:** `xsoar-cli manifest diff [OPTIONS] MANIFEST_PATH`
|
|
64
|
+
|
|
65
|
+
**Options:**
|
|
66
|
+
- `--environment TEXT` - Target environment (default: uses default environment from config)
|
|
67
|
+
|
|
68
|
+
**Arguments:**
|
|
69
|
+
- `MANIFEST_PATH` - Path to the manifest file to compare
|
|
70
|
+
|
|
71
|
+
**Examples:**
|
|
72
|
+
```
|
|
73
|
+
xsoar-cli manifest diff ./xsoar_config.json
|
|
74
|
+
xsoar-cli manifest diff --environment prod ./xsoar_config.json
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## Deploy
|
|
78
|
+
|
|
79
|
+
Install or update content packs on the XSOAR server according to the manifest. Only deploys packs that differ from current installation.
|
|
80
|
+
|
|
81
|
+
**Syntax:** `xsoar-cli manifest deploy [OPTIONS] MANIFEST_PATH`
|
|
82
|
+
|
|
83
|
+
**Options:**
|
|
84
|
+
- `--environment TEXT` - Target environment (default: uses default environment from config)
|
|
85
|
+
- `--verbose` - Show detailed information about skipped packs
|
|
86
|
+
- `--yes` - Skip confirmation prompt
|
|
87
|
+
|
|
88
|
+
**Arguments:**
|
|
89
|
+
- `MANIFEST_PATH` - Path to the manifest file to deploy
|
|
90
|
+
|
|
91
|
+
**Examples:**
|
|
92
|
+
```
|
|
93
|
+
xsoar-cli manifest deploy ./xsoar_config.json
|
|
94
|
+
xsoar-cli manifest deploy --environment prod --yes ./xsoar_config.json
|
|
95
|
+
xsoar-cli manifest deploy --verbose ./xsoar_config.json
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## Manifest File Structure
|
|
99
|
+
|
|
100
|
+
The `xsoar_config.json` file defines content packs to be installed:
|
|
101
|
+
|
|
102
|
+
```json
|
|
103
|
+
{
|
|
104
|
+
"custom_packs": [
|
|
105
|
+
{
|
|
106
|
+
"id": "MyCustomPack",
|
|
107
|
+
"version": "1.0.0",
|
|
108
|
+
"_comment": "Optional documentation comment"
|
|
109
|
+
}
|
|
110
|
+
],
|
|
111
|
+
"marketplace_packs": [
|
|
112
|
+
{
|
|
113
|
+
"id": "CommonScripts",
|
|
114
|
+
"version": "1.20.0"
|
|
115
|
+
}
|
|
116
|
+
]
|
|
117
|
+
}
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
- **custom_packs**: Organization-developed packs stored in artifact repositories
|
|
121
|
+
- **marketplace_packs**: Official Palo Alto Networks content packs
|
|
122
|
+
- **_comment**: Optional field for documentation (preserved during updates)
|
|
File without changes
|