ntermqt 0.1.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.
Files changed (52) hide show
  1. nterm/__init__.py +54 -0
  2. nterm/__main__.py +619 -0
  3. nterm/askpass/__init__.py +22 -0
  4. nterm/askpass/server.py +393 -0
  5. nterm/config.py +158 -0
  6. nterm/connection/__init__.py +17 -0
  7. nterm/connection/profile.py +296 -0
  8. nterm/manager/__init__.py +29 -0
  9. nterm/manager/connect_dialog.py +322 -0
  10. nterm/manager/editor.py +262 -0
  11. nterm/manager/io.py +678 -0
  12. nterm/manager/models.py +346 -0
  13. nterm/manager/settings.py +264 -0
  14. nterm/manager/tree.py +493 -0
  15. nterm/resources.py +48 -0
  16. nterm/session/__init__.py +60 -0
  17. nterm/session/askpass_ssh.py +399 -0
  18. nterm/session/base.py +110 -0
  19. nterm/session/interactive_ssh.py +522 -0
  20. nterm/session/pty_transport.py +571 -0
  21. nterm/session/ssh.py +610 -0
  22. nterm/terminal/__init__.py +11 -0
  23. nterm/terminal/bridge.py +83 -0
  24. nterm/terminal/resources/terminal.html +253 -0
  25. nterm/terminal/resources/terminal.js +414 -0
  26. nterm/terminal/resources/xterm-addon-fit.min.js +8 -0
  27. nterm/terminal/resources/xterm-addon-unicode11.min.js +8 -0
  28. nterm/terminal/resources/xterm-addon-web-links.min.js +8 -0
  29. nterm/terminal/resources/xterm.css +209 -0
  30. nterm/terminal/resources/xterm.min.js +8 -0
  31. nterm/terminal/widget.py +380 -0
  32. nterm/theme/__init__.py +10 -0
  33. nterm/theme/engine.py +456 -0
  34. nterm/theme/stylesheet.py +377 -0
  35. nterm/theme/themes/clean.yaml +0 -0
  36. nterm/theme/themes/default.yaml +36 -0
  37. nterm/theme/themes/dracula.yaml +36 -0
  38. nterm/theme/themes/gruvbox_dark.yaml +36 -0
  39. nterm/theme/themes/gruvbox_hybrid.yaml +38 -0
  40. nterm/theme/themes/gruvbox_light.yaml +36 -0
  41. nterm/vault/__init__.py +32 -0
  42. nterm/vault/credential_manager.py +163 -0
  43. nterm/vault/keychain.py +135 -0
  44. nterm/vault/manager_ui.py +962 -0
  45. nterm/vault/profile.py +219 -0
  46. nterm/vault/resolver.py +250 -0
  47. nterm/vault/store.py +642 -0
  48. ntermqt-0.1.0.dist-info/METADATA +327 -0
  49. ntermqt-0.1.0.dist-info/RECORD +52 -0
  50. ntermqt-0.1.0.dist-info/WHEEL +5 -0
  51. ntermqt-0.1.0.dist-info/entry_points.txt +5 -0
  52. ntermqt-0.1.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,327 @@
1
+ Metadata-Version: 2.4
2
+ Name: ntermqt
3
+ Version: 0.1.0
4
+ Summary: Modern SSH terminal widget for PyQt6 with credential vault and jump host support
5
+ Author: Scott Peterman
6
+ License: GPL-3.0
7
+ Project-URL: Homepage, https://github.com/scottpeterman/nterm
8
+ Project-URL: Repository, https://github.com/scottpeterman/nterm
9
+ Project-URL: Issues, https://github.com/scottpeterman/nterm/issues
10
+ Keywords: ssh,terminal,pyqt6,network,automation
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Environment :: X11 Applications :: Qt
13
+ Classifier: Intended Audience :: System Administrators
14
+ Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
15
+ Classifier: Operating System :: OS Independent
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Topic :: System :: Networking
20
+ Classifier: Topic :: Terminals :: Terminal Emulators/X Terminals
21
+ Requires-Python: >=3.10
22
+ Description-Content-Type: text/markdown
23
+ Requires-Dist: PyQt6>=6.4.0
24
+ Requires-Dist: PyQt6-WebEngine>=6.4.0
25
+ Requires-Dist: paramiko>=3.0.0
26
+ Requires-Dist: cryptography>=41.0.0
27
+ Requires-Dist: pyyaml>=6.0
28
+ Provides-Extra: keyring
29
+ Requires-Dist: keyring>=24.0.0; extra == "keyring"
30
+ Provides-Extra: dev
31
+ Requires-Dist: pytest; extra == "dev"
32
+ Requires-Dist: black; extra == "dev"
33
+ Requires-Dist: pyinstaller; extra == "dev"
34
+ Requires-Dist: build; extra == "dev"
35
+ Requires-Dist: twine; extra == "dev"
36
+
37
+ # nterm
38
+
39
+ **A modern SSH terminal for network engineers**
40
+
41
+ PyQt6 terminal widget with encrypted credential vault, jump host chaining, YubiKey/FIDO2 support, and legacy device compatibility.
42
+
43
+ Built for managing hundreds of devices through bastion hosts with hardware security keys.
44
+
45
+ ![nterm screenshot](https://raw.githubusercontent.com/scottpeterman/nterm/main/screenshots/gruvbox.png)
46
+
47
+ ---
48
+
49
+ ## Features
50
+
51
+ **Terminal**
52
+ - xterm.js rendering via QWebEngineView — full VT100/ANSI support
53
+ - Built-in themes: Catppuccin, Dracula, Nord, Solarized, Gruvbox (dark/light/hybrid)
54
+ - Custom YAML themes with independent terminal and UI colors
55
+ - Tab or window per session — pop sessions to separate windows
56
+ - Unicode, emoji, box-drawing characters
57
+
58
+ **Authentication**
59
+ - SSH Agent with YubiKey/FIDO2 hardware keys
60
+ - Password, key file, keyboard-interactive, certificate auth
61
+ - Multiple auth methods with automatic fallback
62
+ - RSA SHA-1 fallback for legacy devices (OpenSSH < 7.2)
63
+ - Legacy crypto support for old Juniper/Cisco gear
64
+
65
+ **Connection Management**
66
+ - Jump host chaining (unlimited hops)
67
+ - Auto-reconnection with exponential backoff
68
+ - Connection profiles in YAML/JSON
69
+ - Pattern-based credential resolution
70
+
71
+ **Credential Vault**
72
+ - AES-256 encryption with PBKDF2 (480,000 iterations)
73
+ - Pattern matching — map credentials to hosts by wildcard or tag
74
+ - Cross-platform keychain: macOS Keychain, Windows Credential Locker, Linux Secret Service
75
+ - Full PyQt6 management UI
76
+
77
+ ---
78
+
79
+ ## Screenshots
80
+
81
+ | Gruvbox Hybrid Theme | Credential Manager |
82
+ |---------------------|-------------------|
83
+ | ![gruvbox](https://raw.githubusercontent.com/scottpeterman/nterm/main/screenshots/gruvbox.png) | ![vault](https://raw.githubusercontent.com/scottpeterman/nterm/main/screenshots/vault.png) |
84
+
85
+ | Connection Dialog | Multi-vendor Support |
86
+ |----------------------------------------------------------------------------------------------|---------------------|
87
+ | ![connect](https://raw.githubusercontent.com/scottpeterman/nterm/main/screenshots/creds.png) | ![neofetch](https://raw.githubusercontent.com/scottpeterman/nterm/main/screenshots/neofetch.png) |
88
+
89
+ ---
90
+
91
+ ## Installation
92
+
93
+ ### From PyPI
94
+
95
+ ```bash
96
+ pip install nterm
97
+
98
+ # Optional: system keychain support
99
+ pip install nterm[keyring]
100
+
101
+ # Run
102
+ nterm
103
+ ```
104
+
105
+ ### From Source
106
+
107
+ ```bash
108
+ git clone https://github.com/scottpeterman/nterm.git
109
+ cd nterm
110
+
111
+ # Create virtual environment
112
+ python -m venv .venv
113
+ source .venv/bin/activate # Linux/macOS
114
+ # .venv\Scripts\activate # Windows
115
+
116
+ # Install in development mode
117
+ pip install -e .
118
+
119
+ # Optional: system keychain support
120
+ pip install keyring
121
+
122
+ # Run
123
+ nterm
124
+ # or
125
+ python -m nterm
126
+ ```
127
+
128
+ ### Requirements
129
+
130
+ - Python 3.10+
131
+ - PyQt6 with WebEngine
132
+ - paramiko
133
+ - cryptography
134
+ - pyyaml
135
+
136
+ ### Platform Support
137
+
138
+ | Platform | PTY | Keychain |
139
+ |----------|-----|----------|
140
+ | Linux | ✅ Native | Secret Service |
141
+ | macOS | ✅ Native | macOS Keychain |
142
+ | Windows 10+ | ✅ pywinpty | Credential Locker |
143
+
144
+ ---
145
+
146
+ ## Quick Start
147
+
148
+ ### As a Widget
149
+
150
+ ```python
151
+ from PyQt6.QtWidgets import QApplication, QMainWindow
152
+ from nterm import ConnectionProfile, AuthConfig, SSHSession, TerminalWidget, Theme
153
+
154
+ app = QApplication([])
155
+
156
+ terminal = TerminalWidget()
157
+ terminal.set_theme(Theme.gruvbox_hybrid())
158
+
159
+ profile = ConnectionProfile(
160
+ name="router",
161
+ hostname="192.168.1.1",
162
+ auth_methods=[AuthConfig.password_auth("admin", "secret")],
163
+ )
164
+
165
+ session = SSHSession(profile)
166
+ terminal.attach_session(session)
167
+ session.connect()
168
+
169
+ window = QMainWindow()
170
+ window.setCentralWidget(terminal)
171
+ window.resize(1000, 700)
172
+ window.show()
173
+
174
+ app.exec()
175
+ ```
176
+
177
+ ### With Credential Vault
178
+
179
+ ```python
180
+ from nterm.vault import CredentialStore, CredentialResolver
181
+
182
+ store = CredentialStore()
183
+ store.unlock("master-password")
184
+
185
+ # Add credential with pattern matching
186
+ store.add_credential(
187
+ name="network-devices",
188
+ username="admin",
189
+ password="secret",
190
+ match_hosts=["*.network.corp", "192.168.1.*"],
191
+ match_tags=["cisco", "juniper"],
192
+ )
193
+
194
+ # Auto-resolve credentials by hostname
195
+ resolver = CredentialResolver(store)
196
+ profile = resolver.resolve_for_device("switch01.network.corp", tags=["cisco"])
197
+
198
+ session = SSHSession(profile)
199
+ session.connect()
200
+ ```
201
+
202
+ ---
203
+
204
+ ## Themes
205
+
206
+ ### Built-in
207
+
208
+ ```python
209
+ Theme.default() # Catppuccin Mocha
210
+ Theme.dracula() # Dracula
211
+ Theme.nord() # Nord
212
+ Theme.solarized_dark() # Solarized Dark
213
+ Theme.gruvbox_dark() # Gruvbox Dark
214
+ Theme.gruvbox_light() # Gruvbox Light
215
+ Theme.gruvbox_hybrid() # Dark UI + Light terminal
216
+ ```
217
+
218
+ ### Custom YAML
219
+
220
+ ```yaml
221
+ # ~/.nterm/themes/my-theme.yaml
222
+ name: my-theme
223
+
224
+ terminal_colors:
225
+ background: "#1a1b26"
226
+ foreground: "#c0caf5"
227
+ cursor: "#c0caf5"
228
+ black: "#15161e"
229
+ red: "#f7768e"
230
+ green: "#9ece6a"
231
+ yellow: "#e0af68"
232
+ blue: "#7aa2f7"
233
+ magenta: "#bb9af7"
234
+ cyan: "#7dcfff"
235
+ white: "#a9b1d6"
236
+ # ... bright variants
237
+
238
+ # UI chrome (can differ from terminal)
239
+ background_color: "#1a1b26"
240
+ foreground_color: "#c0caf5"
241
+ border_color: "#33467c"
242
+ accent_color: "#7aa2f7"
243
+ ```
244
+
245
+ ---
246
+
247
+ ## Jump Hosts
248
+
249
+ ```python
250
+ profile = ConnectionProfile(
251
+ name="internal-db",
252
+ hostname="db01.internal.corp",
253
+ auth_methods=[AuthConfig.agent_auth("dbadmin")],
254
+ jump_hosts=[
255
+ JumpHostConfig(
256
+ hostname="bastion.corp.com",
257
+ auth=AuthConfig.agent_auth("youruser"),
258
+ requires_touch=True,
259
+ touch_prompt="Touch YubiKey for bastion...",
260
+ ),
261
+ ],
262
+ )
263
+ ```
264
+
265
+ ---
266
+
267
+ ## Legacy Device Support
268
+
269
+ nterm automatically handles old network equipment:
270
+
271
+ - **RSA SHA-1 fallback** for OpenSSH < 7.2 servers
272
+ - **Legacy KEX algorithms**: diffie-hellman-group14-sha1, group1-sha1
273
+ - **Legacy ciphers**: aes128-cbc, 3des-cbc
274
+ - **Auto-detection**: tries modern crypto first, falls back as needed
275
+
276
+ Tested with:
277
+ - Junos 14.x (2016)
278
+ - Cisco IOS 12.2
279
+ - Old Arista EOS
280
+ - Any device running OpenSSH 6.x
281
+
282
+ ---
283
+
284
+ ## Architecture
285
+
286
+ ```
287
+ nterm/
288
+ ├── connection/ # ConnectionProfile, AuthConfig, JumpHostConfig
289
+ ├── session/
290
+ │ ├── ssh.py # SSHSession (Paramiko) with legacy fallback
291
+ │ ├── interactive_ssh.py # Native SSH + PTY
292
+ │ └── pty_transport.py # Cross-platform PTY
293
+ ├── terminal/
294
+ │ ├── widget.py # TerminalWidget (PyQt6 + xterm.js)
295
+ │ └── bridge.py # Qt ↔ JavaScript bridge
296
+ ├── theme/
297
+ │ ├── engine.py # Theme system
298
+ │ └── themes/ # YAML theme files
299
+ ├── vault/
300
+ │ ├── store.py # Encrypted credential storage
301
+ │ ├── resolver.py # Pattern-based resolution
302
+ │ └── manager_ui.py # PyQt6 credential manager
303
+ └── manager/ # Session tree, connection dialogs
304
+ ```
305
+
306
+ ---
307
+
308
+ ## Related Projects
309
+
310
+ - [TerminalTelemetry](https://github.com/scottpeterman/terminaltelemetry) — PyQt6 terminal with network monitoring
311
+ - [Secure Cartography](https://github.com/scottpeterman/secure_cartography) — Network discovery and mapping
312
+
313
+ ---
314
+
315
+ ## License
316
+
317
+ GPLv3
318
+
319
+ ---
320
+
321
+ ## Contributing
322
+
323
+ Contributions welcome:
324
+ - Additional themes
325
+ - Windows testing
326
+ - Session recording/playback
327
+ - Telnet/serial support
@@ -0,0 +1,52 @@
1
+ nterm/__init__.py,sha256=Liu1bya6xi3NnwO9KLqqlYyLD1eS-2HeEdEpJRc2480,1346
2
+ nterm/__main__.py,sha256=bRqfQCnEPvsDYYUTnfJAAhCuuecGm-4H5a8HGhs37xE,20865
3
+ nterm/config.py,sha256=19T28opP-rdLRuxXCGP-qrklAlh4HNbXNTyAwveBhu8,4690
4
+ nterm/resources.py,sha256=SYC8JeF7vVfER93KKRd-tt5b25t0tHTkd7fSJqVDXnI,1447
5
+ nterm/askpass/__init__.py,sha256=UpJBk0EOm0nkRwMVv7YdIB4v75ZJpSYmNsU_GlgzbUg,495
6
+ nterm/askpass/server.py,sha256=5tvjYryyfu-n8Cw2KbucwaZfWiqYnFk-iBAVBI8FMfw,12873
7
+ nterm/connection/__init__.py,sha256=2qQ9LGxUxmwem8deOD2WZVkeD6rIVlTlx5Zh2cUEmxY,261
8
+ nterm/connection/profile.py,sha256=4RMgnRNKCc-dFGEIpmQc_bob5MtzxO04_PljP-qUGLs,9450
9
+ nterm/manager/__init__.py,sha256=_QIeTap5CTL3jdTS1Q16fAt-PrqcNPUVr9gtJ22f0ng,774
10
+ nterm/manager/connect_dialog.py,sha256=yd8g_gYttT_UdflRxSfyss8OQTfrvKLUOMg4Kj8FPNo,11711
11
+ nterm/manager/editor.py,sha256=Fn2YWHJ1EwPYrhKhsi4GTBYwRfCYsHsqgKkLY-LQ8JI,8469
12
+ nterm/manager/io.py,sha256=R5ksWgpEz0VdVCokcgTN5G3PFgp5QYhjjt40OypSWkY,21687
13
+ nterm/manager/models.py,sha256=cvC2HzCRadNG1EYsnZN4C9YS6uolHGcUGGZtt-wzGF4,12237
14
+ nterm/manager/settings.py,sha256=r6MTw_9r1Wl2UX_ALpXIuPbDvJ0D91Y8wRKq6Bfr_3g,9210
15
+ nterm/manager/tree.py,sha256=D1aLVH7xy9m-V1PSwu-GFW1r6UYd93zyufrO0HBRidE,18996
16
+ nterm/session/__init__.py,sha256=FkgHF1WPz78JBOWHSC7LLynG2NqoR6aanNTRlEzsO6I,1612
17
+ nterm/session/askpass_ssh.py,sha256=U-frmLBIXwE2L5ZCEtai91G1dVRSWKLCtxn88t_PqGs,14083
18
+ nterm/session/base.py,sha256=NNFt2uy-rTkwigrHcdnfREk_QZDxNe0CoP16C-7oIWs,2475
19
+ nterm/session/interactive_ssh.py,sha256=qBhVGFdkx4hRyEzx0ZdBZZeiuwCav6BR4UtKqPnCssM,17846
20
+ nterm/session/pty_transport.py,sha256=VLVIr96f5SsDv2oZlb2TgdcaApNCN2ci5PGkbQ41c_g,16906
21
+ nterm/session/ssh.py,sha256=sGOxjBa9FX6GjVwkmfiKsupoLVsrPVk-LSREjlNmAdE,20942
22
+ nterm/terminal/__init__.py,sha256=uFnG366Z166pK-ijT1dZanVSSFVZCiMGeNKXvss_sDg,184
23
+ nterm/terminal/bridge.py,sha256=FSZMArlq-7a3IsKUrOL42MZeDJ4FfdZwC5UTRk1xryc,2860
24
+ nterm/terminal/widget.py,sha256=snUBsH4W0njPogGk3TJYJuvye3YCL1GJSt3cV2YFCeI,13165
25
+ nterm/terminal/resources/terminal.html,sha256=LNtXx19SVANjObNydWoAqkBJloKz_bt0kbN41Z7EFxI,7778
26
+ nterm/terminal/resources/terminal.js,sha256=wZqVhEu-_KASGfDo-s3nmVZKhupI2r-Ak_poIn_1FU8,13224
27
+ nterm/terminal/resources/xterm-addon-fit.min.js,sha256=x45XlcZIes3ySrQ2eY1KnOw4SBAbKBvGWwYfOdtxS-E,1789
28
+ nterm/terminal/resources/xterm-addon-unicode11.min.js,sha256=_sT7CbMSksBfUPmKZYj29IDjq7LMjiwciFs0iGNomBM,7500
29
+ nterm/terminal/resources/xterm-addon-web-links.min.js,sha256=_iizzOZ3_DRg6y7iu111muLnWVW8bzC9V6_EAPu0hK8,3219
30
+ nterm/terminal/resources/xterm.css,sha256=gy8_LGA7Q61DUf8ElwFQzHqHMBQnbbEmpgZcbdgeSHI,5383
31
+ nterm/terminal/resources/xterm.min.js,sha256=_B3TGyIePl-SlIbgeoC0d6iq-dzitPnD_-fdJfNwZV0,283670
32
+ nterm/theme/__init__.py,sha256=ZTywoJliQcFre0Gh7I30n-_7RrPmdR1NHnE4wSkSCsQ,130
33
+ nterm/theme/engine.py,sha256=I9pKmk8rOvJis5-bVgMe-JFTk82zU73-bBXkvsbMi28,15635
34
+ nterm/theme/stylesheet.py,sha256=Ycy-y_kiP-SLcQFrAEdJtbSDtKm4yvBfxEe-N26qlDg,9004
35
+ nterm/theme/themes/clean.yaml,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
36
+ nterm/theme/themes/default.yaml,sha256=niUrI_K8fayPCZDy1gc3hueLtkWjfmm1p1R33JjYgS4,810
37
+ nterm/theme/themes/dracula.yaml,sha256=YKX1cNHw4g0A8KipFC5QEa22xyH8Mu1W0QwpY3hJLyE,810
38
+ nterm/theme/themes/gruvbox_dark.yaml,sha256=cAr-67R7QhW80ncHptpyyrZuUqD65xoSuLtmHeDgQM0,815
39
+ nterm/theme/themes/gruvbox_hybrid.yaml,sha256=Ml7Ed3sTBjcSYVJ9t961KhiG3DwMAdVdRBtzI4eWZg0,936
40
+ nterm/theme/themes/gruvbox_light.yaml,sha256=InqYF-TsLLIzhCHpSSHqSxnest5tu28htQ4AaFN4BFY,820
41
+ nterm/vault/__init__.py,sha256=e1W3GZKOf0FXNerSp1mojl-yaidYIsygnRwTGBd6mfM,708
42
+ nterm/vault/credential_manager.py,sha256=TWAMfjpntPXEJ-4AauDz2PPS0q140sUebFk8AjvC-A0,5347
43
+ nterm/vault/keychain.py,sha256=_2-yUhc2ro-An2zvFlJHYyxozM55iJ4bSseOVKMCNGo,4229
44
+ nterm/vault/manager_ui.py,sha256=qle-W40j6L_pOR0AaOCeyU8myizFTRkISNrloCn0H_Y,34530
45
+ nterm/vault/profile.py,sha256=qM9TJf68RKdjtxo-sJehO7wS4iTi2G26BKbmlmHLA5M,6246
46
+ nterm/vault/resolver.py,sha256=GWB2YR9H1MH98RGQBKvitIsjWT_-wSMLuddZNz4wbns,7800
47
+ nterm/vault/store.py,sha256=fbmABHWRjkZ5t42O7r74D3B_R2mZ0WPY8STPo3fGMdw,21191
48
+ ntermqt-0.1.0.dist-info/METADATA,sha256=MXx0-MnyTuZeSjU7oIsd5lWm3MtTJ1HdscyqwUZdfXk,8595
49
+ ntermqt-0.1.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
50
+ ntermqt-0.1.0.dist-info/entry_points.txt,sha256=5OEnwVRWwTZjFYXaVNzWdFt-gm2QojCLk50sCLnC2y4,93
51
+ ntermqt-0.1.0.dist-info/top_level.txt,sha256=bZdnNLTHNRNqo9jsOQGUWF7h5st0xW_thH0n2QOxWUo,6
52
+ ntermqt-0.1.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,5 @@
1
+ [console_scripts]
2
+ nterm = nterm.__main__:main
3
+
4
+ [gui_scripts]
5
+ nterm-gui = nterm.__main__:main
@@ -0,0 +1 @@
1
+ nterm