typescript-virtual-container 1.5.3 → 1.5.5
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.
- package/README.md +44 -532
- package/dist/.tsbuildinfo +1 -0
- package/dist/SSHMimic/executor.js +23 -5
- package/dist/VirtualPackageManager/index.js +10 -0
- package/dist/VirtualShell/shell.js +158 -11
- package/dist/commands/basename.d.ts +13 -0
- package/dist/commands/basename.js +45 -0
- package/dist/commands/bc.d.ts +2 -0
- package/dist/commands/bc.js +28 -0
- package/dist/commands/file.d.ts +8 -0
- package/dist/commands/file.js +57 -0
- package/dist/commands/fun.d.ts +32 -0
- package/dist/commands/fun.js +172 -0
- package/dist/commands/ip.d.ts +7 -0
- package/dist/commands/ip.js +52 -0
- package/dist/commands/jobs.d.ts +4 -0
- package/dist/commands/jobs.js +27 -0
- package/dist/commands/last.d.ts +13 -0
- package/dist/commands/last.js +68 -0
- package/dist/commands/manuals-bundle.js +598 -6
- package/dist/commands/registry.js +30 -2
- package/dist/commands/runtime.js +24 -3
- package/dist/commands/set.js +20 -0
- package/dist/commands/sh.js +74 -1
- package/dist/commands/tput.d.ts +13 -0
- package/dist/commands/tput.js +76 -0
- package/dist/commands/w.d.ts +7 -0
- package/dist/commands/w.js +38 -0
- package/dist/utils/expand.d.ts +12 -0
- package/dist/utils/expand.js +87 -1
- package/package.json +9 -3
- package/.github/ISSUE_TEMPLATE/bug_report.yml +0 -50
- package/.github/ISSUE_TEMPLATE/feature_request.yml +0 -31
- package/.github/dependabot.yml +0 -27
- package/.github/pull_request_template.md +0 -21
- package/.github/workflows/create-pull-request.yml +0 -85
- package/.github/workflows/publish.yml +0 -25
- package/.github/workflows/test-battery.yml +0 -102
- package/.vscode/settings.json +0 -20
- package/CODE_OF_CONDUCT.md +0 -39
- package/CONTRIBUTING.md +0 -59
- package/HONEYPOT.md +0 -358
- package/SECURITY.md +0 -33
- package/benchmark-results.txt +0 -40
- package/benchmark-virtualshell.ts +0 -88
- package/biome.json +0 -37
- package/build.js +0 -22
- package/builds/fortune-nyx-v1.5.3-directbash-k6.1.0.mjs +0 -1764
- package/builds/fortune-nyx-v1.5.3-ssh-nosftp.js +0 -1764
- package/builds/fortune-nyx-v1.5.3-ssh.cjs +0 -1765
- package/builds/fortune-nyx-v1.5.3-web.min.js +0 -17036
- package/bun.lock +0 -244
- package/docs/.nojekyll +0 -1
- package/docs/app.js +0 -1751
- package/docs/assets/hierarchy.js +0 -1
- package/docs/assets/highlight.css +0 -162
- package/docs/assets/icons.js +0 -18
- package/docs/assets/icons.svg +0 -1
- package/docs/assets/main.js +0 -60
- package/docs/assets/navigation.js +0 -1
- package/docs/assets/search.js +0 -1
- package/docs/assets/style.css +0 -1633
- package/docs/classes/HoneyPot.html +0 -31
- package/docs/classes/IdleManager.html +0 -162
- package/docs/classes/SshClient.html +0 -66
- package/docs/classes/VirtualFileSystem.html +0 -279
- package/docs/classes/VirtualPackageManager.html +0 -63
- package/docs/classes/VirtualSftpServer.html +0 -169
- package/docs/classes/VirtualShell.html +0 -285
- package/docs/classes/VirtualSshServer.html +0 -182
- package/docs/classes/VirtualUserManager.html +0 -276
- package/docs/demo.html +0 -82
- package/docs/functions/assertDiff.html +0 -6
- package/docs/functions/diffSnapshots.html +0 -7
- package/docs/functions/formatDiff.html +0 -6
- package/docs/functions/getArg.html +0 -13
- package/docs/functions/getFlag.html +0 -15
- package/docs/functions/ifFlag.html +0 -11
- package/docs/hierarchy.html +0 -1
- package/docs/index.html +0 -1869
- package/docs/interfaces/AuditLogEntry.html +0 -6
- package/docs/interfaces/CommandContext.html +0 -22
- package/docs/interfaces/CommandResult.html +0 -26
- package/docs/interfaces/ExecStream.html +0 -11
- package/docs/interfaces/HoneyPotStats.html +0 -16
- package/docs/interfaces/IdleManagerOptions.html +0 -7
- package/docs/interfaces/InstalledPackage.html +0 -20
- package/docs/interfaces/NanoEditorSession.html +0 -8
- package/docs/interfaces/PackageDefinition.html +0 -30
- package/docs/interfaces/PackageFile.html +0 -8
- package/docs/interfaces/PasswordChallenge.html +0 -16
- package/docs/interfaces/RemoveOptions.html +0 -4
- package/docs/interfaces/ShellEnv.html +0 -6
- package/docs/interfaces/ShellModule.html +0 -14
- package/docs/interfaces/ShellProperties.html +0 -14
- package/docs/interfaces/ShellStream.html +0 -11
- package/docs/interfaces/SudoChallenge.html +0 -24
- package/docs/interfaces/VfsBaseNode.html +0 -12
- package/docs/interfaces/VfsDiff.html +0 -10
- package/docs/interfaces/VfsDiffEntry.html +0 -6
- package/docs/interfaces/VfsDiffModified.html +0 -10
- package/docs/interfaces/VfsDirectoryNode.html +0 -15
- package/docs/interfaces/VfsFileNode.html +0 -17
- package/docs/interfaces/VfsOptions.html +0 -26
- package/docs/interfaces/VfsSnapshot.html +0 -3
- package/docs/interfaces/VfsSnapshotBaseNode.html +0 -8
- package/docs/interfaces/VfsSnapshotDirectoryNode.html +0 -10
- package/docs/interfaces/VfsSnapshotFileNode.html +0 -12
- package/docs/interfaces/VirtualActiveSession.html +0 -12
- package/docs/interfaces/VirtualSftpServerOptions.html +0 -7
- package/docs/interfaces/VirtualShellVfsLike.html +0 -15
- package/docs/interfaces/VirtualShellVfsOptions.html +0 -3
- package/docs/interfaces/WriteFileOptions.html +0 -6
- package/docs/media/LICENSE +0 -21
- package/docs/modules.html +0 -1
- package/docs/types/ArgParseOptions.html +0 -4
- package/docs/types/CommandMode.html +0 -2
- package/docs/types/CommandOutcome.html +0 -2
- package/docs/types/IdleState.html +0 -1
- package/docs/types/VfsNodeStats.html +0 -2
- package/docs/types/VfsNodeType.html +0 -2
- package/docs/types/VfsPersistenceMode.html +0 -5
- package/docs/types/VfsSnapshotNode.html +0 -2
- package/examples/README.md +0 -288
- package/examples/app.js +0 -1751
- package/examples/app.ts +0 -299
- package/examples/build.js +0 -27
- package/examples/demo.html +0 -33
- package/examples/honeypot-audit.ts +0 -180
- package/examples/honeypot-export.ts +0 -253
- package/examples/honeypot-quickstart.ts +0 -110
- package/examples/index.html +0 -82
- package/examples/server.js +0 -55
- package/polyfills/buffer.js +0 -117
- package/polyfills/node_child_process/index.js +0 -2
- package/polyfills/node_crypto/index.js +0 -167
- package/polyfills/node_events/index.js +0 -9
- package/polyfills/node_fs/index.js +0 -202
- package/polyfills/node_fs/promises.js +0 -4
- package/polyfills/node_os/index.js +0 -9
- package/polyfills/node_path/index.js +0 -28
- package/polyfills/node_vm/index.js +0 -7
- package/polyfills/node_zlib/index.js +0 -3
- package/polyfills/process.js +0 -14
- package/polyfills/ssh2/index.js +0 -75
- package/scripts/build-all.mjs +0 -226
- package/scripts/build-names.mjs +0 -43
- package/scripts/generate-manuals-bundle.mjs +0 -49
- package/scripts/postinstall.js +0 -42
- package/scripts/publish-package.sh +0 -70
- package/src/Honeypot/index.ts +0 -457
- package/src/SSHClient/index.ts +0 -270
- package/src/SSHMimic/exec.ts +0 -49
- package/src/SSHMimic/executor.ts +0 -251
- package/src/SSHMimic/hostKey.ts +0 -21
- package/src/SSHMimic/index.ts +0 -337
- package/src/SSHMimic/loginBanner.ts +0 -36
- package/src/SSHMimic/loginFormat.ts +0 -10
- package/src/SSHMimic/prompt.ts +0 -14
- package/src/SSHMimic/sftp.ts +0 -883
- package/src/VirtualFileSystem/binaryPack.ts +0 -258
- package/src/VirtualFileSystem/index.ts +0 -1193
- package/src/VirtualFileSystem/internalTypes.ts +0 -43
- package/src/VirtualFileSystem/journal.ts +0 -171
- package/src/VirtualFileSystem/path.ts +0 -74
- package/src/VirtualPackageManager/index.ts +0 -996
- package/src/VirtualShell/idleManager.ts +0 -137
- package/src/VirtualShell/index.ts +0 -475
- package/src/VirtualShell/shell.ts +0 -700
- package/src/VirtualShell/shellParser.ts +0 -285
- package/src/VirtualUserManager/index.ts +0 -758
- package/src/bun.d.ts +0 -1
- package/src/commands/adduser.ts +0 -103
- package/src/commands/alias.ts +0 -69
- package/src/commands/apt.ts +0 -233
- package/src/commands/awk.ts +0 -168
- package/src/commands/base64.ts +0 -29
- package/src/commands/cat.ts +0 -52
- package/src/commands/cd.ts +0 -25
- package/src/commands/chmod.ts +0 -85
- package/src/commands/clear.ts +0 -15
- package/src/commands/command-helpers.ts +0 -286
- package/src/commands/cp.ts +0 -83
- package/src/commands/curl.ts +0 -147
- package/src/commands/cut.ts +0 -36
- package/src/commands/date.ts +0 -30
- package/src/commands/declare.ts +0 -49
- package/src/commands/deluser.ts +0 -98
- package/src/commands/df.ts +0 -23
- package/src/commands/diff.ts +0 -43
- package/src/commands/dpkg.ts +0 -180
- package/src/commands/du.ts +0 -56
- package/src/commands/echo.ts +0 -58
- package/src/commands/env.ts +0 -23
- package/src/commands/exit.ts +0 -18
- package/src/commands/export.ts +0 -34
- package/src/commands/find.ts +0 -68
- package/src/commands/free.ts +0 -47
- package/src/commands/grep.ts +0 -116
- package/src/commands/groups.ts +0 -19
- package/src/commands/gzip.ts +0 -88
- package/src/commands/head.ts +0 -52
- package/src/commands/help.ts +0 -152
- package/src/commands/helpers.ts +0 -234
- package/src/commands/history.ts +0 -34
- package/src/commands/hostname.ts +0 -14
- package/src/commands/htop.ts +0 -20
- package/src/commands/id.ts +0 -19
- package/src/commands/index.ts +0 -9
- package/src/commands/kill.ts +0 -19
- package/src/commands/ln.ts +0 -71
- package/src/commands/ls.ts +0 -243
- package/src/commands/lsb-release.ts +0 -63
- package/src/commands/man.ts +0 -31
- package/src/commands/manuals/adduser.txt +0 -11
- package/src/commands/manuals/apt-cache.txt +0 -12
- package/src/commands/manuals/apt.txt +0 -20
- package/src/commands/manuals/awk.txt +0 -13
- package/src/commands/manuals/cat.txt +0 -14
- package/src/commands/manuals/cd.txt +0 -16
- package/src/commands/manuals/chmod.txt +0 -16
- package/src/commands/manuals/clear.txt +0 -10
- package/src/commands/manuals/cp.txt +0 -10
- package/src/commands/manuals/curl.txt +0 -20
- package/src/commands/manuals/date.txt +0 -14
- package/src/commands/manuals/declare.txt +0 -12
- package/src/commands/manuals/deluser.txt +0 -10
- package/src/commands/manuals/df.txt +0 -10
- package/src/commands/manuals/dpkg-query.txt +0 -11
- package/src/commands/manuals/dpkg.txt +0 -14
- package/src/commands/manuals/du.txt +0 -11
- package/src/commands/manuals/echo.txt +0 -11
- package/src/commands/manuals/false.txt +0 -10
- package/src/commands/manuals/find.txt +0 -11
- package/src/commands/manuals/free.txt +0 -12
- package/src/commands/manuals/grep.txt +0 -13
- package/src/commands/manuals/groups.txt +0 -10
- package/src/commands/manuals/gzip.txt +0 -11
- package/src/commands/manuals/head.txt +0 -10
- package/src/commands/manuals/help.txt +0 -11
- package/src/commands/manuals/history.txt +0 -11
- package/src/commands/manuals/hostname.txt +0 -10
- package/src/commands/manuals/id.txt +0 -10
- package/src/commands/manuals/kill.txt +0 -13
- package/src/commands/manuals/ls.txt +0 -20
- package/src/commands/manuals/lsb_release.txt +0 -14
- package/src/commands/manuals/mkdir.txt +0 -10
- package/src/commands/manuals/mv.txt +0 -10
- package/src/commands/manuals/nano.txt +0 -11
- package/src/commands/manuals/neofetch.txt +0 -10
- package/src/commands/manuals/node.txt +0 -13
- package/src/commands/manuals/npm.txt +0 -13
- package/src/commands/manuals/npx.txt +0 -13
- package/src/commands/manuals/passwd.txt +0 -11
- package/src/commands/manuals/ping.txt +0 -10
- package/src/commands/manuals/printf.txt +0 -11
- package/src/commands/manuals/ps.txt +0 -10
- package/src/commands/manuals/pwd.txt +0 -10
- package/src/commands/manuals/python3.txt +0 -13
- package/src/commands/manuals/readlink.txt +0 -10
- package/src/commands/manuals/return.txt +0 -10
- package/src/commands/manuals/rm.txt +0 -10
- package/src/commands/manuals/sed.txt +0 -11
- package/src/commands/manuals/set.txt +0 -11
- package/src/commands/manuals/shift.txt +0 -10
- package/src/commands/manuals/sleep.txt +0 -10
- package/src/commands/manuals/sort.txt +0 -12
- package/src/commands/manuals/source.txt +0 -11
- package/src/commands/manuals/ssh.txt +0 -11
- package/src/commands/manuals/stat.txt +0 -10
- package/src/commands/manuals/su.txt +0 -13
- package/src/commands/manuals/sudo.txt +0 -11
- package/src/commands/manuals/tail.txt +0 -10
- package/src/commands/manuals/tar.txt +0 -19
- package/src/commands/manuals/tee.txt +0 -10
- package/src/commands/manuals/test.txt +0 -11
- package/src/commands/manuals/touch.txt +0 -11
- package/src/commands/manuals/tr.txt +0 -10
- package/src/commands/manuals/trap.txt +0 -10
- package/src/commands/manuals/true.txt +0 -10
- package/src/commands/manuals/type.txt +0 -10
- package/src/commands/manuals/uname.txt +0 -12
- package/src/commands/manuals/uniq.txt +0 -12
- package/src/commands/manuals/unset.txt +0 -10
- package/src/commands/manuals/uptime.txt +0 -11
- package/src/commands/manuals/wc.txt +0 -12
- package/src/commands/manuals/wget.txt +0 -12
- package/src/commands/manuals/which.txt +0 -10
- package/src/commands/manuals/whoami.txt +0 -10
- package/src/commands/manuals/xargs.txt +0 -10
- package/src/commands/manuals-bundle.ts +0 -898
- package/src/commands/mkdir.ts +0 -31
- package/src/commands/mv.ts +0 -50
- package/src/commands/nano.ts +0 -38
- package/src/commands/neofetch.ts +0 -53
- package/src/commands/node.ts +0 -341
- package/src/commands/npm.ts +0 -132
- package/src/commands/passwd.ts +0 -50
- package/src/commands/ping.ts +0 -32
- package/src/commands/printf.ts +0 -129
- package/src/commands/ps.ts +0 -58
- package/src/commands/pwd.ts +0 -9
- package/src/commands/python.ts +0 -2229
- package/src/commands/read.ts +0 -46
- package/src/commands/registry.ts +0 -249
- package/src/commands/rm.ts +0 -42
- package/src/commands/runtime.ts +0 -421
- package/src/commands/sed.ts +0 -68
- package/src/commands/seq.ts +0 -43
- package/src/commands/set.ts +0 -29
- package/src/commands/sh.ts +0 -467
- package/src/commands/shift.ts +0 -63
- package/src/commands/sleep.ts +0 -20
- package/src/commands/sort.ts +0 -46
- package/src/commands/source.ts +0 -52
- package/src/commands/stat.ts +0 -61
- package/src/commands/su.ts +0 -72
- package/src/commands/sudo.ts +0 -76
- package/src/commands/tail.ts +0 -53
- package/src/commands/tar.ts +0 -102
- package/src/commands/tee.ts +0 -36
- package/src/commands/test.ts +0 -137
- package/src/commands/touch.ts +0 -28
- package/src/commands/tr.ts +0 -70
- package/src/commands/tree.ts +0 -20
- package/src/commands/true.ts +0 -27
- package/src/commands/type.ts +0 -48
- package/src/commands/uname.ts +0 -29
- package/src/commands/uniq.ts +0 -39
- package/src/commands/unset.ts +0 -17
- package/src/commands/uptime.ts +0 -54
- package/src/commands/wc.ts +0 -55
- package/src/commands/wget.ts +0 -148
- package/src/commands/which.ts +0 -37
- package/src/commands/who.ts +0 -25
- package/src/commands/whoami.ts +0 -14
- package/src/commands/xargs.ts +0 -31
- package/src/index.ts +0 -67
- package/src/modules/linuxRootfs.ts +0 -1961
- package/src/modules/neofetch.ts +0 -358
- package/src/modules/shellInteractive.ts +0 -57
- package/src/modules/shellRuntime.ts +0 -76
- package/src/self-standalone.ts +0 -542
- package/src/standalone-wo-sftp.ts +0 -38
- package/src/standalone.ts +0 -72
- package/src/types/commands.ts +0 -146
- package/src/types/pipeline.ts +0 -52
- package/src/types/streams.ts +0 -32
- package/src/types/tar-stream.d.ts +0 -38
- package/src/types/vfs.ts +0 -98
- package/src/utils/expand.ts +0 -491
- package/src/utils/perfLogger.ts +0 -72
- package/src/utils/tokenize.ts +0 -98
- package/src/utils/vfsDiff.ts +0 -275
- package/tests/command-helpers.test.ts +0 -116
- package/tests/commands-admin-net.test.ts +0 -441
- package/tests/commands-advanced.test.ts +0 -456
- package/tests/commands-core.test.ts +0 -562
- package/tests/commands-missing.test.ts +0 -570
- package/tests/commands-specific-units.test.ts +0 -327
- package/tests/commands-text-sys.test.ts +0 -445
- package/tests/expand.test.ts +0 -170
- package/tests/helpers.test.ts +0 -97
- package/tests/new-features.test.ts +0 -1036
- package/tests/parser-executor.test.ts +0 -37
- package/tests/sftp.test.ts +0 -323
- package/tests/ssh-exec.test.ts +0 -45
- package/tests/test-helper.ts +0 -79
- package/tests/users.test.ts +0 -86
- package/tsconfig.json +0 -49
- package/typedoc.json +0 -47
package/src/Honeypot/index.ts
DELETED
|
@@ -1,457 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Honeypot tracking and auditing module for virtual shell events.
|
|
3
|
-
*
|
|
4
|
-
* Attaches listeners to VirtualShell, VirtualFileSystem, VirtualUserManager,
|
|
5
|
-
* SshMimic, and SftpMimic instances to log all activity for security auditing,
|
|
6
|
-
* anomaly detection, and forensic analysis.
|
|
7
|
-
*
|
|
8
|
-
* @module honeypot
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
import type { EventEmitter } from "node:events";
|
|
12
|
-
import type { SshMimic } from "../SSHMimic";
|
|
13
|
-
import type { SftpMimic } from "../SSHMimic/sftp";
|
|
14
|
-
import type { PerfLogger } from "../utils/perfLogger";
|
|
15
|
-
import { createPerfLogger } from "../utils/perfLogger";
|
|
16
|
-
import type VirtualFileSystem from "../VirtualFileSystem";
|
|
17
|
-
import type { VirtualShell } from "../VirtualShell";
|
|
18
|
-
import type { VirtualUserManager } from "../VirtualUserManager";
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Audit log entry recorded for each event.
|
|
22
|
-
*/
|
|
23
|
-
export interface AuditLogEntry {
|
|
24
|
-
timestamp: string;
|
|
25
|
-
type: string;
|
|
26
|
-
source: string;
|
|
27
|
-
details: Record<string, unknown>;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* Statistics tracker for honeypot activity.
|
|
32
|
-
*/
|
|
33
|
-
export interface HoneyPotStats {
|
|
34
|
-
authAttempts: number;
|
|
35
|
-
authSuccesses: number;
|
|
36
|
-
authFailures: number;
|
|
37
|
-
commands: number;
|
|
38
|
-
fileWrites: number;
|
|
39
|
-
fileReads: number;
|
|
40
|
-
sessionStarts: number;
|
|
41
|
-
sessionEnds: number;
|
|
42
|
-
userCreated: number;
|
|
43
|
-
userDeleted: number;
|
|
44
|
-
clientConnects: number;
|
|
45
|
-
clientDisconnects: number;
|
|
46
|
-
shellFreezes: number;
|
|
47
|
-
shellThaws: number;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
const perf: PerfLogger = createPerfLogger("HoneyPot");
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* HoneyPot audit and event tracking utility.
|
|
54
|
-
*
|
|
55
|
-
* Singleton-like helper that attaches listeners to virtual shell components
|
|
56
|
-
* and maintains an audit log of all activity.
|
|
57
|
-
*/
|
|
58
|
-
export class HoneyPot {
|
|
59
|
-
private auditLog: AuditLogEntry[] = [];
|
|
60
|
-
private stats: HoneyPotStats = {
|
|
61
|
-
authAttempts: 0,
|
|
62
|
-
authSuccesses: 0,
|
|
63
|
-
authFailures: 0,
|
|
64
|
-
commands: 0,
|
|
65
|
-
fileWrites: 0,
|
|
66
|
-
fileReads: 0,
|
|
67
|
-
sessionStarts: 0,
|
|
68
|
-
sessionEnds: 0,
|
|
69
|
-
userCreated: 0,
|
|
70
|
-
userDeleted: 0,
|
|
71
|
-
clientConnects: 0,
|
|
72
|
-
clientDisconnects: 0,
|
|
73
|
-
shellFreezes: 0,
|
|
74
|
-
shellThaws: 0,
|
|
75
|
-
};
|
|
76
|
-
|
|
77
|
-
private maxLogSize: number;
|
|
78
|
-
/** Reference kept so VFS events can ping the shell's idle manager. */
|
|
79
|
-
private _shell: VirtualShell | null = null;
|
|
80
|
-
|
|
81
|
-
/**
|
|
82
|
-
* Creates a new HoneyPot instance.
|
|
83
|
-
*
|
|
84
|
-
* @param maxLogSize Maximum audit log entries to retain (default: 10000).
|
|
85
|
-
*/
|
|
86
|
-
constructor(maxLogSize: number = 10000) {
|
|
87
|
-
perf.mark("constructor");
|
|
88
|
-
this.maxLogSize = maxLogSize;
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
/**
|
|
92
|
-
* Attaches honeypot listeners to all provided event emitters.
|
|
93
|
-
*
|
|
94
|
-
* @param shell VirtualShell instance.
|
|
95
|
-
* @param vfs VirtualFileSystem instance.
|
|
96
|
-
* @param users VirtualUserManager instance.
|
|
97
|
-
* @param ssh SshMimic instance (optional).
|
|
98
|
-
* @param sftp SftpMimic instance (optional).
|
|
99
|
-
*/
|
|
100
|
-
public attach(
|
|
101
|
-
shell: VirtualShell,
|
|
102
|
-
vfs: VirtualFileSystem,
|
|
103
|
-
users: VirtualUserManager,
|
|
104
|
-
ssh?: SshMimic,
|
|
105
|
-
sftp?: SftpMimic,
|
|
106
|
-
): void {
|
|
107
|
-
perf.mark("attach");
|
|
108
|
-
this._shell = shell;
|
|
109
|
-
this.attachVirtualShell(shell);
|
|
110
|
-
this.attachVirtualFileSystem(vfs);
|
|
111
|
-
this.attachVirtualUserManager(users);
|
|
112
|
-
if (ssh) {
|
|
113
|
-
this.attachSshMimic(ssh);
|
|
114
|
-
}
|
|
115
|
-
if (sftp) {
|
|
116
|
-
this.attachSftpMimic(sftp);
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
/**
|
|
121
|
-
* Attaches to VirtualShell events.
|
|
122
|
-
*/
|
|
123
|
-
private attachVirtualShell(shell: VirtualShell): void {
|
|
124
|
-
(shell as EventEmitter).on("initialized", () => {
|
|
125
|
-
this.log("VirtualShell", "initialized", {});
|
|
126
|
-
});
|
|
127
|
-
|
|
128
|
-
(shell as EventEmitter).on("command", (data: Record<string, unknown>) => {
|
|
129
|
-
this.stats.commands++;
|
|
130
|
-
this.log("VirtualShell", "command", data);
|
|
131
|
-
});
|
|
132
|
-
|
|
133
|
-
(shell as EventEmitter).on(
|
|
134
|
-
"session:start",
|
|
135
|
-
(data: Record<string, unknown>) => {
|
|
136
|
-
this.stats.sessionStarts++;
|
|
137
|
-
this.log("VirtualShell", "session:start", data);
|
|
138
|
-
},
|
|
139
|
-
);
|
|
140
|
-
|
|
141
|
-
(shell as EventEmitter).on("shell:freeze", () => {
|
|
142
|
-
this.stats.shellFreezes++;
|
|
143
|
-
this.log("VirtualShell", "shell:freeze", {});
|
|
144
|
-
});
|
|
145
|
-
|
|
146
|
-
(shell as EventEmitter).on("shell:thaw", () => {
|
|
147
|
-
this.stats.shellThaws++;
|
|
148
|
-
this.log("VirtualShell", "shell:thaw", {});
|
|
149
|
-
});
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
/**
|
|
153
|
-
* Attaches to VirtualFileSystem events.
|
|
154
|
-
* Also pings the shell's idle manager so SFTP/direct VFS activity
|
|
155
|
-
* counts as activity and prevents spurious freezes.
|
|
156
|
-
*/
|
|
157
|
-
private attachVirtualFileSystem(vfs: VirtualFileSystem): void {
|
|
158
|
-
(vfs as EventEmitter).on("file:read", (data: Record<string, unknown>) => {
|
|
159
|
-
this.stats.fileReads++;
|
|
160
|
-
this._shell?.pingIdle();
|
|
161
|
-
this.log("VirtualFileSystem", "file:read", data);
|
|
162
|
-
});
|
|
163
|
-
|
|
164
|
-
(vfs as EventEmitter).on("file:write", (data: Record<string, unknown>) => {
|
|
165
|
-
this.stats.fileWrites++;
|
|
166
|
-
this._shell?.pingIdle();
|
|
167
|
-
this.log("VirtualFileSystem", "file:write", data);
|
|
168
|
-
});
|
|
169
|
-
|
|
170
|
-
(vfs as EventEmitter).on("dir:create", (data: Record<string, unknown>) => {
|
|
171
|
-
this._shell?.pingIdle();
|
|
172
|
-
this.log("VirtualFileSystem", "dir:create", data);
|
|
173
|
-
});
|
|
174
|
-
|
|
175
|
-
(vfs as EventEmitter).on("mirror:flush", () => {
|
|
176
|
-
this.log("VirtualFileSystem", "mirror:flush", {});
|
|
177
|
-
});
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
/**
|
|
181
|
-
* Attaches to VirtualUserManager events.
|
|
182
|
-
*/
|
|
183
|
-
private attachVirtualUserManager(users: VirtualUserManager): void {
|
|
184
|
-
(users as EventEmitter).on("initialized", () => {
|
|
185
|
-
this.log("VirtualUserManager", "initialized", {});
|
|
186
|
-
});
|
|
187
|
-
|
|
188
|
-
(users as EventEmitter).on("user:add", (data: Record<string, unknown>) => {
|
|
189
|
-
this.stats.userCreated++;
|
|
190
|
-
this.log("VirtualUserManager", "user:add", data);
|
|
191
|
-
});
|
|
192
|
-
|
|
193
|
-
(users as EventEmitter).on(
|
|
194
|
-
"user:delete",
|
|
195
|
-
(data: Record<string, unknown>) => {
|
|
196
|
-
this.stats.userDeleted++;
|
|
197
|
-
this.log("VirtualUserManager", "user:delete", data);
|
|
198
|
-
},
|
|
199
|
-
);
|
|
200
|
-
|
|
201
|
-
(users as EventEmitter).on(
|
|
202
|
-
"session:register",
|
|
203
|
-
(data: Record<string, unknown>) => {
|
|
204
|
-
this.log("VirtualUserManager", "session:register", data);
|
|
205
|
-
},
|
|
206
|
-
);
|
|
207
|
-
|
|
208
|
-
(users as EventEmitter).on(
|
|
209
|
-
"session:unregister",
|
|
210
|
-
(data: Record<string, unknown>) => {
|
|
211
|
-
this.stats.sessionEnds++;
|
|
212
|
-
this.log("VirtualUserManager", "session:unregister", data);
|
|
213
|
-
},
|
|
214
|
-
);
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
/**
|
|
218
|
-
* Attaches to SshMimic events.
|
|
219
|
-
*/
|
|
220
|
-
private attachSshMimic(ssh: SshMimic): void {
|
|
221
|
-
(ssh as EventEmitter).on("start", (data: Record<string, unknown>) => {
|
|
222
|
-
this.log("SshMimic", "start", data);
|
|
223
|
-
});
|
|
224
|
-
|
|
225
|
-
(ssh as EventEmitter).on("stop", () => {
|
|
226
|
-
this.log("SshMimic", "stop", {});
|
|
227
|
-
});
|
|
228
|
-
|
|
229
|
-
(ssh as EventEmitter).on(
|
|
230
|
-
"auth:success",
|
|
231
|
-
(data: Record<string, unknown>) => {
|
|
232
|
-
this.stats.authAttempts++;
|
|
233
|
-
this.stats.authSuccesses++;
|
|
234
|
-
this.log("SshMimic", "auth:success", data);
|
|
235
|
-
},
|
|
236
|
-
);
|
|
237
|
-
|
|
238
|
-
(ssh as EventEmitter).on(
|
|
239
|
-
"auth:failure",
|
|
240
|
-
(data: Record<string, unknown>) => {
|
|
241
|
-
this.stats.authAttempts++;
|
|
242
|
-
this.stats.authFailures++;
|
|
243
|
-
this.log("SshMimic", "auth:failure", data);
|
|
244
|
-
},
|
|
245
|
-
);
|
|
246
|
-
|
|
247
|
-
(ssh as EventEmitter).on("client:connect", () => {
|
|
248
|
-
this.stats.clientConnects++;
|
|
249
|
-
this.log("SshMimic", "client:connect", {});
|
|
250
|
-
});
|
|
251
|
-
|
|
252
|
-
(ssh as EventEmitter).on(
|
|
253
|
-
"client:disconnect",
|
|
254
|
-
(data: Record<string, unknown>) => {
|
|
255
|
-
this.stats.clientDisconnects++;
|
|
256
|
-
this.log("SshMimic", "client:disconnect", data);
|
|
257
|
-
},
|
|
258
|
-
);
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
/**
|
|
262
|
-
* Attaches to SftpMimic events.
|
|
263
|
-
*/
|
|
264
|
-
private attachSftpMimic(sftp: SftpMimic): void {
|
|
265
|
-
(sftp as EventEmitter).on("start", (data: Record<string, unknown>) => {
|
|
266
|
-
this.log("SftpMimic", "start", data);
|
|
267
|
-
});
|
|
268
|
-
|
|
269
|
-
(sftp as EventEmitter).on("stop", () => {
|
|
270
|
-
this.log("SftpMimic", "stop", {});
|
|
271
|
-
});
|
|
272
|
-
|
|
273
|
-
(sftp as EventEmitter).on(
|
|
274
|
-
"auth:success",
|
|
275
|
-
(data: Record<string, unknown>) => {
|
|
276
|
-
this.stats.authAttempts++;
|
|
277
|
-
this.stats.authSuccesses++;
|
|
278
|
-
this.log("SftpMimic", "auth:success", data);
|
|
279
|
-
},
|
|
280
|
-
);
|
|
281
|
-
|
|
282
|
-
(sftp as EventEmitter).on(
|
|
283
|
-
"auth:failure",
|
|
284
|
-
(data: Record<string, unknown>) => {
|
|
285
|
-
this.stats.authAttempts++;
|
|
286
|
-
this.stats.authFailures++;
|
|
287
|
-
this.log("SftpMimic", "auth:failure", data);
|
|
288
|
-
},
|
|
289
|
-
);
|
|
290
|
-
|
|
291
|
-
(sftp as EventEmitter).on("client:connect", () => {
|
|
292
|
-
this.stats.clientConnects++;
|
|
293
|
-
this.log("SftpMimic", "client:connect", {});
|
|
294
|
-
});
|
|
295
|
-
|
|
296
|
-
(sftp as EventEmitter).on(
|
|
297
|
-
"client:disconnect",
|
|
298
|
-
(data: Record<string, unknown>) => {
|
|
299
|
-
this.stats.clientDisconnects++;
|
|
300
|
-
this.log("SftpMimic", "client:disconnect", data);
|
|
301
|
-
},
|
|
302
|
-
);
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
/**
|
|
306
|
-
* Records an audit log entry.
|
|
307
|
-
*
|
|
308
|
-
* @param source Event source (e.g., "SshMimic", "VirtualFileSystem").
|
|
309
|
-
* @param type Event type.
|
|
310
|
-
* @param details Event-specific data.
|
|
311
|
-
*/
|
|
312
|
-
private log(
|
|
313
|
-
source: string,
|
|
314
|
-
type: string,
|
|
315
|
-
details: Record<string, unknown>,
|
|
316
|
-
): void {
|
|
317
|
-
const entry: AuditLogEntry = {
|
|
318
|
-
timestamp: new Date().toISOString(),
|
|
319
|
-
type,
|
|
320
|
-
source,
|
|
321
|
-
details,
|
|
322
|
-
};
|
|
323
|
-
|
|
324
|
-
this.auditLog.push(entry);
|
|
325
|
-
|
|
326
|
-
// Trim log if exceeds max size
|
|
327
|
-
if (this.auditLog.length > this.maxLogSize) {
|
|
328
|
-
this.auditLog = this.auditLog.slice(-this.maxLogSize);
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
// Console output for real-time monitoring
|
|
332
|
-
console.log(`[AUDIT] ${entry.timestamp} | ${source} | ${type}`, details);
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
/**
|
|
336
|
-
* Returns audit log entries matching optional filters.
|
|
337
|
-
*
|
|
338
|
-
* @param type Optional event type filter.
|
|
339
|
-
* @param source Optional source filter.
|
|
340
|
-
* @returns Filtered audit log entries.
|
|
341
|
-
*/
|
|
342
|
-
public getAuditLog(type?: string, source?: string): AuditLogEntry[] {
|
|
343
|
-
perf.mark("getAuditLog");
|
|
344
|
-
return this.auditLog.filter(
|
|
345
|
-
(entry) =>
|
|
346
|
-
(!type || entry.type === type) && (!source || entry.source === source),
|
|
347
|
-
);
|
|
348
|
-
}
|
|
349
|
-
|
|
350
|
-
/**
|
|
351
|
-
* Returns current activity statistics.
|
|
352
|
-
*
|
|
353
|
-
* @returns Snapshot of honeypot stats.
|
|
354
|
-
*/
|
|
355
|
-
public getStats(): Readonly<HoneyPotStats> {
|
|
356
|
-
perf.mark("getStats");
|
|
357
|
-
return Object.freeze({ ...this.stats });
|
|
358
|
-
}
|
|
359
|
-
|
|
360
|
-
/**
|
|
361
|
-
* Clears audit log and resets statistics.
|
|
362
|
-
*/
|
|
363
|
-
public reset(): void {
|
|
364
|
-
perf.mark("reset");
|
|
365
|
-
this.auditLog = [];
|
|
366
|
-
this.stats = {
|
|
367
|
-
authAttempts: 0,
|
|
368
|
-
authSuccesses: 0,
|
|
369
|
-
authFailures: 0,
|
|
370
|
-
commands: 0,
|
|
371
|
-
fileWrites: 0,
|
|
372
|
-
fileReads: 0,
|
|
373
|
-
sessionStarts: 0,
|
|
374
|
-
sessionEnds: 0,
|
|
375
|
-
userCreated: 0,
|
|
376
|
-
userDeleted: 0,
|
|
377
|
-
clientConnects: 0,
|
|
378
|
-
clientDisconnects: 0,
|
|
379
|
-
shellFreezes: 0,
|
|
380
|
-
shellThaws: 0,
|
|
381
|
-
};
|
|
382
|
-
}
|
|
383
|
-
|
|
384
|
-
/**
|
|
385
|
-
* Returns recent log entries in reverse chronological order.
|
|
386
|
-
*
|
|
387
|
-
* @param limit Number of recent entries to return (default: 100).
|
|
388
|
-
* @returns Recent audit log entries.
|
|
389
|
-
*/
|
|
390
|
-
public getRecent(limit: number = 100): AuditLogEntry[] {
|
|
391
|
-
perf.mark("getRecent");
|
|
392
|
-
return this.auditLog.slice(Math.max(0, this.auditLog.length - limit));
|
|
393
|
-
}
|
|
394
|
-
|
|
395
|
-
/**
|
|
396
|
-
* Detects potential security issues based on activity patterns.
|
|
397
|
-
*
|
|
398
|
-
* @returns Array of anomalies detected.
|
|
399
|
-
*/
|
|
400
|
-
public detectAnomalies(): Array<{
|
|
401
|
-
type: string;
|
|
402
|
-
severity: "low" | "medium" | "high";
|
|
403
|
-
message: string;
|
|
404
|
-
}> {
|
|
405
|
-
perf.mark("detectAnomalies");
|
|
406
|
-
const anomalies: Array<{
|
|
407
|
-
type: string;
|
|
408
|
-
severity: "low" | "medium" | "high";
|
|
409
|
-
message: string;
|
|
410
|
-
}> = [];
|
|
411
|
-
|
|
412
|
-
// High auth failure rate
|
|
413
|
-
if (
|
|
414
|
-
this.stats.authAttempts > 0 &&
|
|
415
|
-
this.stats.authFailures / this.stats.authAttempts > 0.5
|
|
416
|
-
) {
|
|
417
|
-
anomalies.push({
|
|
418
|
-
type: "high_auth_failure_rate",
|
|
419
|
-
severity: "medium",
|
|
420
|
-
message: `Auth failure rate: ${(
|
|
421
|
-
(this.stats.authFailures / this.stats.authAttempts) * 100
|
|
422
|
-
).toFixed(1)}%`,
|
|
423
|
-
});
|
|
424
|
-
}
|
|
425
|
-
|
|
426
|
-
// Excessive auth failures in short time
|
|
427
|
-
if (this.stats.authFailures > 10) {
|
|
428
|
-
anomalies.push({
|
|
429
|
-
type: "excessive_auth_failures",
|
|
430
|
-
severity: "high",
|
|
431
|
-
message: `${this.stats.authFailures} authentication failures detected`,
|
|
432
|
-
});
|
|
433
|
-
}
|
|
434
|
-
|
|
435
|
-
// Unusual command execution volume
|
|
436
|
-
if (this.stats.commands > 1000) {
|
|
437
|
-
anomalies.push({
|
|
438
|
-
type: "high_command_volume",
|
|
439
|
-
severity: "low",
|
|
440
|
-
message: `${this.stats.commands} commands executed`,
|
|
441
|
-
});
|
|
442
|
-
}
|
|
443
|
-
|
|
444
|
-
// Unusual file write volume
|
|
445
|
-
if (this.stats.fileWrites > 500) {
|
|
446
|
-
anomalies.push({
|
|
447
|
-
type: "high_write_volume",
|
|
448
|
-
severity: "medium",
|
|
449
|
-
message: `${this.stats.fileWrites} file write operations`,
|
|
450
|
-
});
|
|
451
|
-
}
|
|
452
|
-
|
|
453
|
-
return anomalies;
|
|
454
|
-
}
|
|
455
|
-
}
|
|
456
|
-
|
|
457
|
-
export default HoneyPot;
|
package/src/SSHClient/index.ts
DELETED
|
@@ -1,270 +0,0 @@
|
|
|
1
|
-
import { runCommand } from "../commands";
|
|
2
|
-
import type { CommandResult } from "../types/commands";
|
|
3
|
-
import type { PerfLogger } from "../utils/perfLogger";
|
|
4
|
-
import { createPerfLogger } from "../utils/perfLogger";
|
|
5
|
-
import type { VirtualShell } from "../VirtualShell";
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Programmatic client for executing shell commands against a virtual shell.
|
|
9
|
-
*
|
|
10
|
-
* Maintains working-directory state across invocations and runs commands as a
|
|
11
|
-
* single authenticated user without SSH transport overhead.
|
|
12
|
-
*
|
|
13
|
-
* @example
|
|
14
|
-
* ```ts
|
|
15
|
-
* const shell = new VirtualShell("typescript-vm");
|
|
16
|
-
* const client = new SshClient(shell, "alice");
|
|
17
|
-
* const result = await client.cd("/tmp");
|
|
18
|
-
* const list = await client.ls();
|
|
19
|
-
* ```
|
|
20
|
-
*/
|
|
21
|
-
const perf: PerfLogger = createPerfLogger("SshClient");
|
|
22
|
-
|
|
23
|
-
export class SshClient {
|
|
24
|
-
private currentCwd = "/";
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Creates a programmatic client bound to a virtual shell and user.
|
|
28
|
-
*
|
|
29
|
-
* @param shell Parent virtual shell instance.
|
|
30
|
-
* @param username Login user for all commands.
|
|
31
|
-
*/
|
|
32
|
-
constructor(
|
|
33
|
-
private shell: VirtualShell,
|
|
34
|
-
private username: string,
|
|
35
|
-
) {
|
|
36
|
-
perf.mark("constructor");
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* Executes raw shell command.
|
|
41
|
-
*
|
|
42
|
-
* @param command Unparsed command line.
|
|
43
|
-
* @returns Command result with stdout/stderr/exitCode.
|
|
44
|
-
*/
|
|
45
|
-
async exec(command: string): Promise<CommandResult> {
|
|
46
|
-
perf.mark("exec");
|
|
47
|
-
const vfs = this.shell.getVfs();
|
|
48
|
-
const users = this.shell.getUsers();
|
|
49
|
-
const hostname = this.shell.getHostname();
|
|
50
|
-
|
|
51
|
-
if (!vfs || !users) {
|
|
52
|
-
throw new Error("SSH client not started");
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
const result = runCommand(
|
|
56
|
-
command,
|
|
57
|
-
this.username,
|
|
58
|
-
hostname,
|
|
59
|
-
"exec",
|
|
60
|
-
this.currentCwd,
|
|
61
|
-
this.shell,
|
|
62
|
-
);
|
|
63
|
-
|
|
64
|
-
// Handle async results
|
|
65
|
-
const resolved = result instanceof Promise ? await result : result;
|
|
66
|
-
|
|
67
|
-
// Propagate cwd changes (cd, su, etc.)
|
|
68
|
-
if (resolved.nextCwd && (resolved.exitCode ?? 0) === 0) {
|
|
69
|
-
this.currentCwd = resolved.nextCwd;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
return resolved;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
/**
|
|
76
|
-
* Lists directory contents.
|
|
77
|
-
*
|
|
78
|
-
* @param path Target directory, defaults to cwd.
|
|
79
|
-
* @returns Result with directory listing in stdout.
|
|
80
|
-
*/
|
|
81
|
-
async ls(path?: string): Promise<CommandResult> {
|
|
82
|
-
perf.mark("ls");
|
|
83
|
-
const target = path ?? ".";
|
|
84
|
-
return this.exec(`ls ${target}`);
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
/**
|
|
88
|
-
* Prints current working directory.
|
|
89
|
-
*
|
|
90
|
-
* @returns Result with cwd path in stdout.
|
|
91
|
-
*/
|
|
92
|
-
async pwd(): Promise<CommandResult> {
|
|
93
|
-
perf.mark("pwd");
|
|
94
|
-
return this.exec("pwd");
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
/**
|
|
98
|
-
* Changes working directory.
|
|
99
|
-
*
|
|
100
|
-
* @param path Target directory path.
|
|
101
|
-
* @returns Result; updates internal cwd on success.
|
|
102
|
-
*/
|
|
103
|
-
async cd(path: string): Promise<CommandResult> {
|
|
104
|
-
perf.mark("cd");
|
|
105
|
-
const result = await this.exec(`cd ${path}`);
|
|
106
|
-
if (result.nextCwd && result.exitCode !== 1) {
|
|
107
|
-
this.currentCwd = result.nextCwd;
|
|
108
|
-
}
|
|
109
|
-
return result;
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
/**
|
|
113
|
-
* Reads file content.
|
|
114
|
-
*
|
|
115
|
-
* @param path File path.
|
|
116
|
-
* @returns Result with file content in stdout.
|
|
117
|
-
*/
|
|
118
|
-
async cat(path: string): Promise<CommandResult> {
|
|
119
|
-
perf.mark("cat");
|
|
120
|
-
return this.exec(`cat ${path}`);
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
/**
|
|
124
|
-
* Creates directory.
|
|
125
|
-
*
|
|
126
|
-
* @param path Directory path.
|
|
127
|
-
* @param recursive When true, create parents.
|
|
128
|
-
* @returns Result from mkdir command.
|
|
129
|
-
*/
|
|
130
|
-
async mkdir(path: string, recursive = false): Promise<CommandResult> {
|
|
131
|
-
perf.mark("mkdir");
|
|
132
|
-
const flag = recursive ? "-p " : "";
|
|
133
|
-
return this.exec(`mkdir ${flag}${path}`);
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
/**
|
|
137
|
-
* Creates file (empty).
|
|
138
|
-
*
|
|
139
|
-
* @param path File path.
|
|
140
|
-
* @returns Result from touch command.
|
|
141
|
-
*/
|
|
142
|
-
async touch(path: string): Promise<CommandResult> {
|
|
143
|
-
perf.mark("touch");
|
|
144
|
-
return this.exec(`touch ${path}`);
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
/**
|
|
148
|
-
* Removes file or directory.
|
|
149
|
-
*
|
|
150
|
-
* @param path Target path.
|
|
151
|
-
* @param recursive When true, delete directory tree.
|
|
152
|
-
* @returns Result from rm command.
|
|
153
|
-
*/
|
|
154
|
-
async rm(path: string, recursive = false): Promise<CommandResult> {
|
|
155
|
-
perf.mark("rm");
|
|
156
|
-
const flag = recursive ? "-r " : "";
|
|
157
|
-
return this.exec(`rm ${flag}${path}`);
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
/**
|
|
161
|
-
* Writes file content.
|
|
162
|
-
*
|
|
163
|
-
* @param path Target file path.
|
|
164
|
-
* @param content Text to write.
|
|
165
|
-
* @returns Result from touch/write simulation.
|
|
166
|
-
*/
|
|
167
|
-
async writeFile(path: string, content: string): Promise<CommandResult> {
|
|
168
|
-
perf.mark("writeFile");
|
|
169
|
-
const vfs = this.shell.getVfs();
|
|
170
|
-
if (!vfs) {
|
|
171
|
-
throw new Error("SSH client not started");
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
try {
|
|
175
|
-
this.shell.writeFileAsUser(this.username, path, content);
|
|
176
|
-
return { stdout: `File '${path}' written`, exitCode: 0 };
|
|
177
|
-
} catch (error) {
|
|
178
|
-
return {
|
|
179
|
-
stderr: `Failed to write '${path}': ${error instanceof Error ? error.message : String(error)}`,
|
|
180
|
-
exitCode: 1,
|
|
181
|
-
};
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
/**
|
|
186
|
-
* Reads file content programmatically.
|
|
187
|
-
*
|
|
188
|
-
* @param path Target file path.
|
|
189
|
-
* @returns File content as string or error in result.
|
|
190
|
-
*/
|
|
191
|
-
async readFile(path: string): Promise<CommandResult> {
|
|
192
|
-
perf.mark("readFile");
|
|
193
|
-
const vfs = this.shell.getVfs();
|
|
194
|
-
if (!vfs) {
|
|
195
|
-
throw new Error("SSH client not started");
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
try {
|
|
199
|
-
const content = vfs.readFile(path);
|
|
200
|
-
return { stdout: content, exitCode: 0 };
|
|
201
|
-
} catch (error) {
|
|
202
|
-
return {
|
|
203
|
-
stderr: `Failed to read '${path}': ${error instanceof Error ? error.message : String(error)}`,
|
|
204
|
-
exitCode: 1,
|
|
205
|
-
};
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
/**
|
|
210
|
-
* Gets current working directory.
|
|
211
|
-
*
|
|
212
|
-
* @returns Normalized cwd path.
|
|
213
|
-
*/
|
|
214
|
-
getCwd(): string {
|
|
215
|
-
perf.mark("getCwd");
|
|
216
|
-
return this.currentCwd;
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
/**
|
|
220
|
-
* Gets logged-in username.
|
|
221
|
-
*
|
|
222
|
-
* @returns Associated username.
|
|
223
|
-
*/
|
|
224
|
-
getUsername(): string {
|
|
225
|
-
perf.mark("getUsername");
|
|
226
|
-
return this.username;
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
/**
|
|
230
|
-
* Renders tree view of directory.
|
|
231
|
-
*
|
|
232
|
-
* @param path Target directory, defaults to cwd.
|
|
233
|
-
* @returns Result with ASCII tree in stdout.
|
|
234
|
-
*/
|
|
235
|
-
async tree(path?: string): Promise<CommandResult> {
|
|
236
|
-
perf.mark("tree");
|
|
237
|
-
const target = path ?? ".";
|
|
238
|
-
return this.exec(`tree ${target}`);
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
/**
|
|
242
|
-
* Shows current user.
|
|
243
|
-
*
|
|
244
|
-
* @returns Result from whoami command.
|
|
245
|
-
*/
|
|
246
|
-
async whoami(): Promise<CommandResult> {
|
|
247
|
-
perf.mark("whoami");
|
|
248
|
-
return this.exec("whoami");
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
/**
|
|
252
|
-
* Shows hostname.
|
|
253
|
-
*
|
|
254
|
-
* @returns Result from hostname command.
|
|
255
|
-
*/
|
|
256
|
-
async hostname(): Promise<CommandResult> {
|
|
257
|
-
perf.mark("hostname");
|
|
258
|
-
return this.exec("hostname");
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
/**
|
|
262
|
-
* Lists active users/sessions.
|
|
263
|
-
*
|
|
264
|
-
* @returns Result from who command.
|
|
265
|
-
*/
|
|
266
|
-
async who(): Promise<CommandResult> {
|
|
267
|
-
perf.mark("who");
|
|
268
|
-
return this.exec("who");
|
|
269
|
-
}
|
|
270
|
-
}
|