edf-plasma-cli 1.0.0__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.
File without changes
@@ -0,0 +1,34 @@
1
+ # file generated by setuptools-scm
2
+ # don't change, don't track in version control
3
+
4
+ __all__ = [
5
+ "__version__",
6
+ "__version_tuple__",
7
+ "version",
8
+ "version_tuple",
9
+ "__commit_id__",
10
+ "commit_id",
11
+ ]
12
+
13
+ TYPE_CHECKING = False
14
+ if TYPE_CHECKING:
15
+ from typing import Tuple
16
+ from typing import Union
17
+
18
+ VERSION_TUPLE = Tuple[Union[int, str], ...]
19
+ COMMIT_ID = Union[str, None]
20
+ else:
21
+ VERSION_TUPLE = object
22
+ COMMIT_ID = object
23
+
24
+ version: str
25
+ __version__: str
26
+ __version_tuple__: VERSION_TUPLE
27
+ version_tuple: VERSION_TUPLE
28
+ commit_id: COMMIT_ID
29
+ __commit_id__: COMMIT_ID
30
+
31
+ __version__ = version = '1.0.0'
32
+ __version_tuple__ = version_tuple = (1, 0, 0)
33
+
34
+ __commit_id__ = commit_id = 'gac0edb2f0'
@@ -0,0 +1,16 @@
1
+ """Command module"""
2
+
3
+ from .abc import Format
4
+ from .dissect import setup_command as setup_dissect_command
5
+ from .list import setup_command as setup_list_command
6
+
7
+ _COMMANDS = (
8
+ setup_dissect_command,
9
+ setup_list_command,
10
+ )
11
+
12
+
13
+ def setup_commands(cmd):
14
+ """Setup commands"""
15
+ for setup_command in _COMMANDS:
16
+ setup_command(cmd)
@@ -0,0 +1,45 @@
1
+ """Base for command implementation"""
2
+
3
+ from enum import Enum
4
+ from json import dumps
5
+
6
+ from rich.box import ROUNDED
7
+ from rich.console import Console
8
+ from rich.table import Column, Table
9
+
10
+ CONSOLE = Console()
11
+
12
+
13
+ class Format(Enum):
14
+ """Output format"""
15
+
16
+ RICH = 'rich'
17
+ JSON = 'json'
18
+
19
+
20
+ class FileFormat(Enum):
21
+ """File format"""
22
+
23
+ CSV = 'csv'
24
+ JSONL = 'jsonl'
25
+
26
+
27
+ def display_table(out_fmt: Format, headers, rows, **kwargs):
28
+ """Build and print table"""
29
+ final_kwargs = {
30
+ 'box': ROUNDED,
31
+ 'row_styles': ['dim', ''],
32
+ }
33
+ final_kwargs.update(kwargs)
34
+ if out_fmt == Format.RICH:
35
+ final_headers = [
36
+ Column(header) if isinstance(header, str) else Column(**header)
37
+ for header in headers
38
+ ]
39
+ table = Table(*final_headers, **final_kwargs)
40
+ for row in rows:
41
+ table.add_row(*row)
42
+ CONSOLE.print(table)
43
+ return
44
+ for row in rows:
45
+ print(dumps(dict(zip(headers, row))))
@@ -0,0 +1,156 @@
1
+ """dissect command implementation"""
2
+
3
+ from pathlib import Path
4
+ from platform import node
5
+
6
+ from edf_plasma_core.helper.csv import write_csv_gz
7
+ from edf_plasma_core.helper.filtering import Filter
8
+ from edf_plasma_core.helper.json import write_jsonl_gz
9
+ from edf_plasma_core.helper.logging import get_logger
10
+ from edf_plasma_core.helper.matching import regexp
11
+ from edf_plasma_core.dissector import (
12
+ DissectionContext,
13
+ Dissector,
14
+ DissectorList,
15
+ get_dissectors,
16
+ )
17
+
18
+ from .abc import FileFormat, display_table
19
+
20
+ _LOGGER = get_logger('cli.command.dissect')
21
+ _HOSTNAME_REPL_PATTERN = regexp(r'[^\w]+')
22
+ _OUTPUT_FORMAT_STRATEGY = {
23
+ FileFormat.CSV: ('.csv.gz', write_csv_gz),
24
+ FileFormat.JSONL: (
25
+ '.jsonl.gz',
26
+ lambda filepath, _, records: write_jsonl_gz(filepath, records),
27
+ ),
28
+ }
29
+ _GETATTR_STRATEGY = {
30
+ 'slug': lambda dissector: {dissector.slug},
31
+ 'tags': lambda dissector: {tag.value for tag in dissector.tags},
32
+ }
33
+
34
+
35
+ def _select(filter_spec: str, dissectors: DissectorList) -> DissectorList:
36
+ attribute, values = filter_spec.split(':', 1)
37
+ filter_ = Filter(include=set(values.split(',')))
38
+ getattr_ = _GETATTR_STRATEGY[attribute]
39
+ return [
40
+ dissector
41
+ for dissector in dissectors
42
+ if filter_.accept(getattr_(dissector))
43
+ ]
44
+
45
+
46
+ def _run_dissector(
47
+ dissector: Dissector,
48
+ target: Path,
49
+ hostname: str,
50
+ file_format: FileFormat,
51
+ prefix: bool,
52
+ output_directory: Path,
53
+ ) -> tuple[Path, Path]:
54
+ targets = [target]
55
+ if target.is_dir():
56
+ targets = list(dissector.select(target))
57
+ hostname = _HOSTNAME_REPL_PATTERN.sub('_', hostname).upper()
58
+ ctx_list = [
59
+ DissectionContext(
60
+ dissector=dissector.slug,
61
+ hostname=hostname,
62
+ source=str(target),
63
+ filepath=target,
64
+ )
65
+ for target in targets
66
+ ]
67
+ prefix = f'{hostname}_' if prefix else ''
68
+ output_directory.mkdir(parents=True, exist_ok=True)
69
+ extension, write_records_to_file = _OUTPUT_FORMAT_STRATEGY[file_format]
70
+ out_filepath = output_directory / f'{prefix}{dissector.slug}{extension}'
71
+ err_filepath = (
72
+ output_directory / f'{prefix}{dissector.slug}_error{extension}'
73
+ )
74
+ write_records_to_file(
75
+ out_filepath,
76
+ dissector.table_schema.names,
77
+ dissector.dissect_many(ctx_list),
78
+ )
79
+ write_records_to_file(
80
+ err_filepath,
81
+ dissector.error_table_schema.names,
82
+ dissector.process_errors(ctx_list),
83
+ )
84
+ return out_filepath, err_filepath
85
+
86
+
87
+ def _dissect_cmd(args):
88
+ rows = []
89
+ dissectors = get_dissectors()
90
+ if args.filter:
91
+ try:
92
+ dissectors = _select(args.filter, dissectors)
93
+ except KeyError:
94
+ _LOGGER.error(
95
+ "invalid filter attribute, available attributes are %s",
96
+ list(_GETATTR_STRATEGY.keys()),
97
+ )
98
+ return
99
+ for dissector in dissectors:
100
+ file_format = FileFormat(args.file_format)
101
+ out_filepath, err_filepath = _run_dissector(
102
+ dissector,
103
+ args.target,
104
+ args.hostname,
105
+ file_format,
106
+ args.prefix,
107
+ args.output_directory,
108
+ )
109
+ rows.append(
110
+ [
111
+ dissector.slug,
112
+ str(out_filepath.resolve()),
113
+ str(err_filepath.resolve()),
114
+ ]
115
+ )
116
+ display_table(
117
+ args.format,
118
+ [
119
+ 'dissector',
120
+ {'header': 'out_filepath', 'overflow': 'fold'},
121
+ {'header': 'err_filepath', 'overflow': 'fold'},
122
+ ],
123
+ rows,
124
+ show_header=False,
125
+ )
126
+
127
+
128
+ def setup_command(cmd):
129
+ """Setup init command parser"""
130
+ dissect = cmd.add_parser('dissect', help="Run a single dissector")
131
+ dissect.add_argument(
132
+ '--file-format',
133
+ '--ff',
134
+ choices=[fmt.value for fmt in FileFormat],
135
+ default=FileFormat.CSV.value,
136
+ help="Output file format",
137
+ )
138
+ dissect.add_argument(
139
+ '--prefix',
140
+ action='store_true',
141
+ help="Prefix output file with hostname",
142
+ )
143
+ dissect.add_argument(
144
+ '--hostname', default=node(), help="Hostname for given artifact"
145
+ )
146
+ dissect.add_argument(
147
+ '--filter',
148
+ help="Dissector filter, e.g. 'tags:ios' or 'slug:microsoft_lnk,microsoft_mft'",
149
+ )
150
+ dissect.add_argument(
151
+ 'target', type=Path, help="Filepath or directory to dissect"
152
+ )
153
+ dissect.add_argument(
154
+ 'output_directory', type=Path, help="Dissector output directory"
155
+ )
156
+ dissect.set_defaults(func=_dissect_cmd)
@@ -0,0 +1,27 @@
1
+ """list command implementation"""
2
+
3
+ from edf_plasma_core.dissector import get_dissectors
4
+
5
+ from .abc import display_table
6
+
7
+
8
+ def _list_cmd(args):
9
+ display_table(
10
+ args.format,
11
+ ['slug', 'tags', 'description'],
12
+ (
13
+ [
14
+ dissector.slug,
15
+ ','.join(sorted(tag.value for tag in dissector.tags)),
16
+ dissector.description,
17
+ ]
18
+ for dissector in get_dissectors()
19
+ ),
20
+ show_header=False,
21
+ )
22
+
23
+
24
+ def setup_command(cmd):
25
+ """Setup init command parser"""
26
+ list_ = cmd.add_parser('list', aliases=['ls'], help="List dissectors")
27
+ list_.set_defaults(func=_list_cmd)
edf_plasma_cli/main.py ADDED
@@ -0,0 +1,70 @@
1
+ """Plasma main program"""
2
+
3
+ from argparse import ArgumentParser
4
+ from importlib.util import spec_from_file_location, module_from_spec
5
+ from pathlib import Path
6
+ from sys import modules, exit as sys_exit
7
+
8
+ from edf_plasma_core.helper.logging import get_logger
9
+ # load dissectors
10
+ import edf_plasma_dissectors as _
11
+
12
+ from .__version__ import version
13
+ from .command import Format, setup_commands
14
+
15
+ _LOGGER = get_logger('cli')
16
+
17
+
18
+ def _parse_args():
19
+ _LOGGER.info("Plasma v%s", version)
20
+ parser = ArgumentParser(description=f"Plasma v{version}")
21
+ parser.add_argument(
22
+ '--plugin-directory',
23
+ '-p',
24
+ type=Path,
25
+ help="Plugin directory to register extra dissectors",
26
+ )
27
+ parser.add_argument(
28
+ '--format',
29
+ '-f',
30
+ choices=[fmt.value for fmt in Format],
31
+ default=Format.RICH.value,
32
+ help="Output format",
33
+ )
34
+ cmd = parser.add_subparsers(dest='cmd')
35
+ cmd.required = True
36
+ setup_commands(cmd)
37
+ args = parser.parse_args()
38
+ args.format = Format(args.format)
39
+ return args
40
+
41
+
42
+ def _import_from_file(plugin: Path):
43
+ spec = spec_from_file_location(plugin.stem, plugin)
44
+ module = module_from_spec(spec)
45
+ modules[plugin.stem] = module
46
+ spec.loader.exec_module(module)
47
+
48
+
49
+ def _import_from_directory(plugin_directory: Path):
50
+ if not plugin_directory:
51
+ return
52
+ if not plugin_directory.is_dir():
53
+ return
54
+ for plugin in plugin_directory.glob('*.py'):
55
+ if not plugin.is_file():
56
+ continue
57
+ _import_from_file(plugin)
58
+
59
+
60
+ def app():
61
+ """Application entrypoint"""
62
+ args = _parse_args()
63
+ _import_from_directory(args.plugin_directory)
64
+ exit_code = 0
65
+ try:
66
+ args.func(args)
67
+ except:
68
+ _LOGGER.exception("exception caught in main handler!")
69
+ exit_code = 1
70
+ sys_exit(exit_code)
@@ -0,0 +1,236 @@
1
+ Metadata-Version: 2.4
2
+ Name: edf-plasma-cli
3
+ Version: 1.0.0
4
+ Summary: EDF Plasma CLI
5
+ Author-email: CERT-EDF <cert@edf.fr>
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/cert-edf/plasma
8
+ Project-URL: Repository, https://github.com/cert-edf/plasma
9
+ Project-URL: Bug Tracker, https://github.com/cert-edf/plasma/issues
10
+ Keywords: edf,plasma,forensic,artifact,dissector,normalizer,cli
11
+ Classifier: Development Status :: 5 - Production/Stable
12
+ Classifier: Intended Audience :: End Users/Desktop
13
+ Classifier: Operating System :: POSIX :: Linux
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3 :: Only
16
+ Classifier: Topic :: Utilities
17
+ Classifier: Topic :: Security
18
+ Requires-Python: >=3.12
19
+ Description-Content-Type: text/markdown
20
+ License-File: LICENSE
21
+ Requires-Dist: edf-plasma-dissectors~=1.0
22
+ Dynamic: license-file
23
+
24
+ # EDF Plasma CLI
25
+
26
+ ## Introduction
27
+
28
+ This package implements a command line interface to perform dissection of forensics
29
+ artifacts from the command line using Plasma Framework's dissectors.
30
+
31
+ <br>
32
+
33
+ ## Setup
34
+
35
+ ```bash
36
+ # first, install edf-plasma-dissectors dependencies
37
+ apt install autoconf \
38
+ automake \
39
+ autopoint \
40
+ build-essential \
41
+ git \
42
+ libsystemd-dev \
43
+ libtool \
44
+ pkg-config \
45
+ python3-dev \
46
+ python3-venv
47
+ # create a virtual environment
48
+ python3 -m venv venv
49
+ # install edf-plasma-cli (will also install edf-plasma-core and edf-plasma-dissectors)
50
+ venv/bin/python -m pip install edf-plasma-cli
51
+ # start dissecting artifacts using dissect command
52
+ venv/bin/plasma -h
53
+ ```
54
+
55
+ <br>
56
+
57
+ ## Usage
58
+
59
+ > [!TIP]
60
+ > - Use `-f` to switch from `rich` output to `json` output to allow piping into `jq` for automation purpose
61
+ > - Use `-p` to load custom plugins from a directory
62
+
63
+ <br>
64
+
65
+ ### List available dissectors
66
+
67
+ ```bash
68
+ venv/bin/plasma list
69
+ ```
70
+ ```
71
+ [2025-09-17T09:52:49] INFO (plasma.cli): Plasma v1.0.0
72
+ ╭────────────────────────────┬───────────────────────┬─────────────────────────────────────────────────╮
73
+ │ android_mvt_appops │ android,mvt │ Dissect MVT Android appops output │
74
+ │ android_mvt_files │ android,mvt │ Dissect MVT Android files output │
75
+ │ android_mvt_packages │ android,mvt │ Dissect MVT Android packages output │
76
+ │ android_mvt_packages_perms │ android,mvt │ Dissect MVT Android packages permissions output │
77
+ │ android_mvt_processes │ android,mvt │ Dissect MVT Android processes output │
78
+ │ android_mvt_sms │ android,mvt │ Dissect MVT Android sms output │
79
+ │ elf_ctor_dtor │ elf,linux │ Dissect ELF constructors and destructors │
80
+ │ elf_export │ elf,linux │ Dissect ELF binary exported symbols │
81
+ │ elf_import │ elf,linux │ Dissect ELF binary imported symbols │
82
+ │ elf_info │ elf,linux │ Dissect ELF information │
83
+ │ elf_library │ elf,linux │ Dissect ELF binary needed libraries │
84
+ │ elf_section │ elf,linux │ Dissect ELF binary sections │
85
+ │ elf_segment │ elf,linux │ Dissect ELF binary segments │
86
+ │ generic_chromium_history │ generic,linux,windows │ Dissect Chromium download and visit history │
87
+ │ generic_firefox_history │ generic,linux,windows │ Dissect Firefox download and visit history │
88
+ │ generic_ssh_pub_key │ generic,linux,windows │ Dissect SSH public key │
89
+ │ ios_mvt_analytics_ad_daily │ ios,mvt │ Dissect MVT iOS os analytics ad daily output │
90
+ │ ios_mvt_apps │ ios,mvt │ Dissect MVT iOS apps output │
91
+ │ ios_mvt_datausage │ ios,mvt │ Dissect MVT iOS datausage output │
92
+ │ ios_mvt_manifest │ ios,mvt │ Dissect MVT iOS manifest output │
93
+ │ ios_mvt_safari_history │ ios,mvt │ Dissect MVT iOS safari history output │
94
+ │ ios_mvt_safari_state │ ios,mvt │ Dissect MVT iOS safari state output │
95
+ │ ios_mvt_shortcuts │ ios,mvt │ Dissect MVT iOS shortcuts output │
96
+ │ ios_mvt_sms │ ios,mvt │ Dissect MVT iOS sms output │
97
+ │ ios_mvt_tcc │ ios,mvt │ Dissect MVT iOS tcc output │
98
+ │ ios_mvt_webkit_rsrc_load │ ios,mvt │ Dissect MVT iOS webkit resource load output │
99
+ │ ios_mvt_whatsapp │ ios,mvt │ Dissect MVT iOS whatsapp output │
100
+ │ ios_sysdiag_bluetooth │ ios,sysdiag │ Dissect iOS sysdiagnose bluetooth status output │
101
+ │ ios_sysdiag_disk │ ios,sysdiag │ Dissect iOS sysdiagnose disk output │
102
+ │ ios_sysdiag_mount │ ios,sysdiag │ Dissect iOS sysdiagnose mount output │
103
+ │ ios_sysdiag_ps │ ios,sysdiag │ Dissect iOS sysdiagnose ps output │
104
+ │ ios_sysdiag_remotectl │ ios,sysdiag │ Dissect iOS sysdiagnose remotectl output │
105
+ │ ios_sysdiag_shutdown │ ios,sysdiag │ Dissect iOS sysdiagnose shutdown output │
106
+ │ ios_sysdiag_wifi │ ios,sysdiag │ Dissect iOS sysdiagnose disk output │
107
+ │ linux_apt_history │ linux │ Dissect apt history log │
108
+ │ linux_apt_sources │ linux │ Dissect apt sources │
109
+ │ linux_at_acl │ linux │ Dissect at.allow and at.deny │
110
+ │ linux_at_jobs │ linux │ Dissect atjobs │
111
+ │ linux_auditd │ linux │ Dissect auditd log │
112
+ │ linux_authlog │ linux │ Dissect auth.log* and secure* journals │
113
+ │ linux_crontab │ linux │ Dissect crontabs │
114
+ │ linux_dpkg │ linux │ Dissect dpkg │
115
+ │ linux_fslist │ linux │ Dissect file list │
116
+ │ linux_fstab │ linux │ Dissect fstab │
117
+ │ linux_group │ linux │ Dissect group │
118
+ │ linux_history │ linux │ Dissect *_history files │
119
+ │ linux_hosts │ linux │ Dissect hosts │
120
+ │ linux_journal_auth │ linux │ Dissect auth events from systemd journal │
121
+ │ linux_journal_cron │ linux │ Dissect cron events from systemd journal │
122
+ │ linux_journal_ftp │ linux │ Dissect ftp events from systemd journal │
123
+ │ linux_logrotate │ linux │ Dissect logrotate │
124
+ │ linux_netstat │ linux │ Network connections │
125
+ │ linux_passwd │ linux │ Dissect passwd │
126
+ │ linux_resolv │ linux │ Dissect resolv │
127
+ │ linux_shadow │ linux │ Dissect shadow │
128
+ │ linux_systemd_service │ linux │ Dissect systemd service │
129
+ │ linux_systemd_timer │ linux │ Dissect systemd timer │
130
+ │ linux_udev_rules │ linux │ Dissect udev rules │
131
+ │ linux_usbguard_device │ linux │ Dissect device events from usbguard log │
132
+ │ linux_usbguard_policy │ linux │ Dissect policy events from usbguard log │
133
+ │ linux_wtmp_utmp │ linux │ Dissect utmp, wtmp and btmp binary logs │
134
+ │ linux_xdg_autostart │ linux │ Dissect xdg autostart │
135
+ │ linux_yum_history │ linux │ Dissect yum history log │
136
+ │ linux_yum_sources │ linux │ Dissect yum sources │
137
+ │ pcap_dns_answers │ pcap │ Dissect DNS answers from PCAP │
138
+ │ pcap_dns_queries │ pcap │ Dissect DNS queries from PCAP │
139
+ │ pcap_http_requests │ pcap │ Dissect DNS http requests from PCAP │
140
+ │ pcap_proto_stats │ pcap │ Dissect protocols from PCAP │
141
+ │ pcap_tcp_conv │ pcap │ Dissect TCP conversations from PCAP │
142
+ │ pcap_tls_cert │ pcap │ Dissect TLS certificates from PCAP │
143
+ │ pcap_tls_client_hello │ pcap │ Dissect TLS client hello from PCAP │
144
+ │ pcap_tls_server_hello │ pcap │ Dissect TLS server hello from PCAP │
145
+ │ pcap_udp_conv │ pcap │ Dissect UDP conversations from PCAP │
146
+ │ pe_ctor_dtor │ pe,windows │ Dissect PE constructors and destructors │
147
+ │ pe_export │ pe,windows │ Dissect PE exported symbols │
148
+ │ pe_import │ pe,windows │ Dissect PE imported symbols │
149
+ │ pe_info │ pe,windows │ Dissect PE information │
150
+ │ pe_resource │ pe,windows │ Dissect PE resources │
151
+ │ pe_rich │ pe,windows │ Dissect PE rich header │
152
+ │ pe_section │ pe,windows │ Dissect PE sections │
153
+ │ pe_signature │ pe,windows │ Dissect PE signatures │
154
+ │ windows_appx │ windows │ Dissect AppX manifest files │
155
+ │ windows_evtx │ windows │ Dissect events from EVTX files │
156
+ │ windows_iis │ windows │ Dissect IIS journal entries │
157
+ │ windows_lnk │ windows │ Dissect LNK │
158
+ │ windows_jumplist │ windows │ Dissect jumplist entries │
159
+ │ windows_mft │ windows │ Dissect entries from NTFS MFT │
160
+ │ windows_mssql │ windows │ Dissect MSSQL ERRORLOG entries │
161
+ │ windows_netstat │ windows │ Network connections │
162
+ │ windows_powershell │ windows │ Dissect powershell command line history │
163
+ │ windows_prefetch │ windows │ Dissect prefetch │
164
+ │ windows_registry │ windows │ Dissect registry hives │
165
+ │ windows_srudb │ windows │ Dissect SRUDB.dat │
166
+ │ windows_task │ windows │ Dissect scheduled tasks │
167
+ │ windows_usnj │ windows │ Dissect NTFS USN journal │
168
+ │ windows_webcache │ windows │ Dissect WebCacheV01.dat │
169
+ │ windows_wmi │ windows │ WMI event filter/consumer bindings │
170
+ │ windows_zone_identifier │ windows │ Dissect Zone.Identifier ADS │
171
+ ╰────────────────────────────┴───────────────────────┴─────────────────────────────────────────────────╯
172
+ ```
173
+
174
+ <br>
175
+
176
+ ### List available dissectors
177
+
178
+ > [!TIP]
179
+ > Use `--fiter` to select dissectors by `tags` or by `slug`
180
+
181
+ ```bash
182
+ plasma dissect --filter 'slug:linux_authlog,linux_wtmp_utmp' /tmp/demo/target /tmp/demo/output
183
+ ```
184
+ ```
185
+ [2025-09-17T10:06:13] INFO (plasma.cli): Plasma v1.0.0
186
+ INFO (plasma.dissectors.abc): file selected: linux_authlog (filepath=/tmp/demo/target/auth.log.4.gz)
187
+ INFO (plasma.dissectors.abc): file selected: linux_authlog (filepath=/tmp/demo/target/auth.log.3.gz)
188
+ INFO (plasma.dissectors.abc): file selected: linux_authlog (filepath=/tmp/demo/target/auth.log)
189
+ INFO (plasma.dissectors.abc): file selected: linux_authlog (filepath=/tmp/demo/target/auth.log.2.gz)
190
+ INFO (plasma.dissectors.abc): file selected: linux_authlog (filepath=/tmp/demo/target/auth.log.1)
191
+ INFO (plasma.dissectors.abc): dissect many start: linux_authlog (files=5)
192
+ INFO (plasma.dissectors.abc): dissection start: linux_authlog (filepath=/tmp/demo/target/auth.log.4.gz)
193
+ INFO (plasma.dissectors.abc): dissection complete: linux_authlog (records=2307, errors=0, time=0:00:00.012953)
194
+ INFO (plasma.dissectors.abc): dissection start: linux_authlog (filepath=/tmp/demo/target/auth.log.3.gz)
195
+ [2025-09-17T10:06:14] INFO (plasma.dissectors.abc): dissection complete: linux_authlog (records=2151, errors=0, time=0:00:00.012987)
196
+ INFO (plasma.dissectors.abc): dissection start: linux_authlog (filepath=/tmp/demo/target/auth.log)
197
+ INFO (plasma.dissectors.abc): dissection complete: linux_authlog (records=785, errors=0, time=0:00:00.004493)
198
+ INFO (plasma.dissectors.abc): dissection start: linux_authlog (filepath=/tmp/demo/target/auth.log.2.gz)
199
+ INFO (plasma.dissectors.abc): dissection complete: linux_authlog (records=1726, errors=0, time=0:00:00.010326)
200
+ INFO (plasma.dissectors.abc): dissection start: linux_authlog (filepath=/tmp/demo/target/auth.log.1)
201
+ INFO (plasma.dissectors.abc): dissection complete: linux_authlog (records=4580, errors=0, time=0:00:00.024124)
202
+ INFO (plasma.dissectors.abc): dissection many complete: linux_authlog (files=5, errors=0, time=0:00:00.069889)
203
+ INFO (plasma.dissectors.abc): file selected: linux_wtmp_utmp (filepath=/tmp/demo/target/wtmp)
204
+ INFO (plasma.dissectors.abc): dissect many start: linux_wtmp_utmp (files=1)
205
+ INFO (plasma.dissectors.abc): dissection start: linux_wtmp_utmp (filepath=/tmp/demo/target/wtmp)
206
+ INFO (plasma.dissectors.abc): dissection complete: linux_wtmp_utmp (records=1842, errors=0, time=0:00:00.106052)
207
+ INFO (plasma.dissectors.abc): dissection many complete: linux_wtmp_utmp (files=1, errors=0, time=0:00:00.107151)
208
+ ╭─────────────────┬─────────────────────────────────────────┬───────────────────────────────────────────────╮
209
+ │ linux_authlog │ /tmp/demo/output/linux_authlog.csv.gz │ /tmp/demo/output/linux_authlog_error.csv.gz │
210
+ │ linux_wtmp_utmp │ /tmp/demo/output/linux_wtmp_utmp.csv.gz │ /tmp/demo/output/linux_wtmp_utmp_error.csv.gz │
211
+ ╰─────────────────┴─────────────────────────────────────────┴───────────────────────────────────────────────╯
212
+ ```
213
+
214
+ <br>
215
+
216
+ ## License
217
+
218
+ Distributed under the [MIT License](LICENSE).
219
+
220
+ <br>
221
+
222
+ ## Contributing
223
+
224
+ Contributions are welcome. See [CONTRIBUTING.md](https://github.com/CERT-EDF/plasma/blob/main/CONTRIBUTING.md).
225
+
226
+ ## Past contributors (before open sourcing)
227
+
228
+ - [koromodako](https://github.com/koromodako)
229
+ - [SPToast](https://github.com/SPToast)
230
+ - [alex532h](https://github.com/alex532h)
231
+
232
+ <br>
233
+
234
+ ## Security
235
+
236
+ To report a (suspected) security issue, see [SECURITY.md](https://github.com/CERT-EDF/plasma/blob/main/SECURITY.md).
@@ -0,0 +1,13 @@
1
+ edf_plasma_cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ edf_plasma_cli/__version__.py,sha256=9YOwLYSyRvoACgH0BeOxo1c69BZ4K5TV7anyKnWRL8U,712
3
+ edf_plasma_cli/main.py,sha256=DrF3WO0kEbA3DV8FuuhVA3GwBVqc5TJGrYqdm-gcngg,1828
4
+ edf_plasma_cli/command/__init__.py,sha256=AworCEwsfpGIYx3ErZ_b-3DV1qfWx1d4fWRJLl0D8Tg,343
5
+ edf_plasma_cli/command/abc.py,sha256=ng-8nwJ-_low08bXAHo7bDDRH_4bQslp9qZlhDD22tQ,985
6
+ edf_plasma_cli/command/dissect.py,sha256=goAIhAS4thkUDmm0PSyJC_38Vkg07QzO8FSxYA1BHYI,4593
7
+ edf_plasma_cli/command/list.py,sha256=HiHRmPEJIzcxQCoIlg2224EiehZZWbKFqJPmnuGiyJg,670
8
+ edf_plasma_cli-1.0.0.dist-info/licenses/LICENSE,sha256=u7ksjywIwisybgov0N66RBD_mV-gct9GTm52932s2QU,1064
9
+ edf_plasma_cli-1.0.0.dist-info/METADATA,sha256=HK-1I0GskFo67QMd_bcVwg29JZ38Kzzw350E0eJ6sEA,18156
10
+ edf_plasma_cli-1.0.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
11
+ edf_plasma_cli-1.0.0.dist-info/entry_points.txt,sha256=444GwzUer_wKIa0u3qTSu9ojCRQBVSGuOf3AOuiVSOQ,51
12
+ edf_plasma_cli-1.0.0.dist-info/top_level.txt,sha256=9NqR1kcilfFnRDLGSq9b8gJk-lIxmlea43S0dMGzLQQ,15
13
+ edf_plasma_cli-1.0.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (80.9.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ plasma = edf_plasma_cli.main:app
@@ -0,0 +1,20 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 CERT-EDF
4
+ Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ of this software and associated documentation files (the "Software"), to deal
6
+ in the Software without restriction, including without limitation the rights
7
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ copies of the Software, and to permit persons to whom the Software is
9
+ furnished to do so, subject to the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be included in all
12
+ copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20
+ SOFTWARE.
@@ -0,0 +1 @@
1
+ edf_plasma_cli