machineconfig 5.79__py3-none-any.whl → 5.82__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.

Potentially problematic release.


This version of machineconfig might be problematic. Click here for more details.

@@ -67,4 +67,6 @@ def get_app():
67
67
  nw_apps.command(name="a", help="Add SSH identity (private key) to this machine", hidden=True)(add_ssh_identity)
68
68
  nw_apps.command(name="show-address", help="[A] Show this computer addresses on network")(show_address)
69
69
  nw_apps.command(name="a", help="Show this computer addresses on network", hidden=True)(show_address)
70
+ nw_apps.command(name="debug-ssh", help="🐛 [d] Debug SSH connection")(debug_ssh)
71
+ nw_apps.command(name="d", help="Debug SSH connection", hidden=True)(debug_ssh)
70
72
  return nw_apps
@@ -83,6 +83,27 @@ def ssh_debug_linux() -> dict[str, dict[str, str | bool]]:
83
83
  results["ssh_service"] = {"status": "warning", "message": "systemctl not found, cannot check service status", "action": "Check SSH service manually"}
84
84
  console.print(Panel("⚠️ systemctl not found\n💡 Check SSH service status manually", title="[bold yellow]Warning[/bold yellow]", border_style="yellow"))
85
85
 
86
+ console.print(Panel("🌐 Checking network interfaces and IP addresses...", title="[bold blue]Network Interfaces[/bold blue]", border_style="blue"))
87
+
88
+ try:
89
+ ip_addr_check = subprocess.run(["ip", "addr", "show"], capture_output=True, text=True, check=False)
90
+ if ip_addr_check.returncode == 0:
91
+ ip_output = ip_addr_check.stdout
92
+ import re
93
+ inet_pattern = re.compile(r'inet\s+(\d+\.\d+\.\d+\.\d+)/\d+.*scope\s+global')
94
+ ip_addresses = inet_pattern.findall(ip_output)
95
+
96
+ if ip_addresses:
97
+ results["network_interfaces"] = {"status": "ok", "message": f"Found {len(ip_addresses)} network interface(s)", "action": ""}
98
+ console.print(Panel("✅ Network interfaces found:\n" + "\n".join([f" • {ip}" for ip in ip_addresses]), title="[bold green]IP Addresses[/bold green]", border_style="green"))
99
+ else:
100
+ results["network_interfaces"] = {"status": "warning", "message": "No global IP addresses found", "action": "Check network configuration"}
101
+ issues_found.append("No network IP addresses")
102
+ console.print(Panel("⚠️ No global IP addresses found\n💡 This machine may not be reachable on the network\n💡 Check: ip addr show", title="[bold yellow]Warning[/bold yellow]", border_style="yellow"))
103
+ except FileNotFoundError:
104
+ results["network_interfaces"] = {"status": "warning", "message": "ip command not found", "action": "Check network manually"}
105
+ console.print(Panel("⚠️ 'ip' command not found\n💡 Try: ifconfig", title="[bold yellow]Warning[/bold yellow]", border_style="yellow"))
106
+
86
107
  console.print(Panel("🔌 Checking SSH port and listening status...", title="[bold blue]Network Status[/bold blue]", border_style="blue"))
87
108
 
88
109
  sshd_config_paths = [PathExtended("/etc/ssh/sshd_config"), PathExtended("/etc/sshd_config")]
@@ -129,8 +150,20 @@ def ssh_debug_linux() -> dict[str, dict[str, str | bool]]:
129
150
  if listening_check.returncode == 0:
130
151
  listening_output = listening_check.stdout
131
152
  if f":{ssh_port}" in listening_output:
132
- results["ssh_listening"] = {"status": "ok", "message": f"SSH is listening on port {ssh_port}", "action": ""}
133
- console.print(Panel(f" SSH is listening on port {ssh_port}", title="[bold green]OK[/bold green]", border_style="green"))
153
+ ssh_lines = [line for line in listening_output.split("\n") if f":{ssh_port}" in line]
154
+ listening_on_all = any("0.0.0.0" in line or "[::]" in line for line in ssh_lines)
155
+ listening_on_localhost_only = all("127.0.0.1" in line or "[::1]" in line for line in ssh_lines)
156
+
157
+ if listening_on_localhost_only:
158
+ results["ssh_listening"] = {"status": "error", "message": f"SSH is listening ONLY on localhost (127.0.0.1:{ssh_port}), not accessible from network", "action": "Edit /etc/ssh/sshd_config, check ListenAddress, restart SSH"}
159
+ issues_found.append("SSH listening only on localhost")
160
+ console.print(Panel(f"❌ SSH is listening ONLY on localhost (127.0.0.1:{ssh_port})\n💡 This prevents external connections!\n💡 Check /etc/ssh/sshd_config for 'ListenAddress'\n💡 Remove or comment out 'ListenAddress 127.0.0.1'\n💡 Or change to 'ListenAddress 0.0.0.0'\n💡 Then: sudo systemctl restart ssh", title="[bold red]Critical Issue[/bold red]", border_style="red"))
161
+ elif listening_on_all:
162
+ results["ssh_listening"] = {"status": "ok", "message": f"SSH is listening on all interfaces (0.0.0.0:{ssh_port})", "action": ""}
163
+ console.print(Panel(f"✅ SSH is listening on all interfaces (0.0.0.0:{ssh_port})\n✅ Should be accessible from network", title="[bold green]OK[/bold green]", border_style="green"))
164
+ else:
165
+ results["ssh_listening"] = {"status": "ok", "message": f"SSH is listening on port {ssh_port}", "action": ""}
166
+ console.print(Panel(f"✅ SSH is listening on port {ssh_port}\n\nListening on:\n" + "\n".join([f" {line.strip()}" for line in ssh_lines[:3]]), title="[bold green]OK[/bold green]", border_style="green"))
134
167
  else:
135
168
  results["ssh_listening"] = {"status": "error", "message": f"SSH is NOT listening on port {ssh_port}", "action": "Check if SSH service is running and configured correctly"}
136
169
  issues_found.append(f"SSH not listening on port {ssh_port}")
@@ -206,7 +239,9 @@ def ssh_debug_linux() -> dict[str, dict[str, str | bool]]:
206
239
  hosts_deny = PathExtended("/etc/hosts.deny")
207
240
  if hosts_deny.exists():
208
241
  hosts_deny_content = hosts_deny.read_text(encoding="utf-8")
209
- if "sshd" in hosts_deny_content.lower() or "all" in hosts_deny_content.lower():
242
+ active_lines = [line.strip() for line in hosts_deny_content.splitlines() if line.strip() and not line.strip().startswith("#")]
243
+ active_content_lower = " ".join(active_lines).lower()
244
+ if "sshd" in active_content_lower or "all" in active_content_lower:
210
245
  results["hosts_deny"] = {"status": "error", "message": "/etc/hosts.deny may be blocking SSH connections", "action": "Review /etc/hosts.deny and remove SSH blocks"}
211
246
  issues_found.append("/etc/hosts.deny blocking SSH")
212
247
  console.print(Panel("❌ /etc/hosts.deny may be blocking SSH\n💡 Check: cat /etc/hosts.deny\n💡 Remove any lines blocking 'sshd' or 'ALL'", title="[bold red]Critical Issue[/bold red]", border_style="red"))
@@ -285,6 +320,30 @@ def ssh_debug_linux() -> dict[str, dict[str, str | bool]]:
285
320
  results["ssh_logs"] = {"status": "warning", "message": "SSH log files not found", "action": "Check journalctl: sudo journalctl -u ssh"}
286
321
  console.print(Panel("⚠️ SSH log files not found\n💡 Check: sudo journalctl -u ssh -n 50", title="[bold yellow]Warning[/bold yellow]", border_style="yellow"))
287
322
 
323
+ console.print(Panel("🧪 Testing local SSH connection...", title="[bold blue]Connection Test[/bold blue]", border_style="blue"))
324
+
325
+ try:
326
+ local_user = os.environ.get("USER", os.environ.get("USERNAME", "unknown"))
327
+ ssh_test = subprocess.run(["ssh", "-o", "ConnectTimeout=5", "-o", "StrictHostKeyChecking=no", "-o", "BatchMode=yes", f"{local_user}@localhost", "echo", "test"], capture_output=True, text=True, check=False, timeout=10)
328
+
329
+ if ssh_test.returncode == 0:
330
+ results["local_ssh_test"] = {"status": "ok", "message": "Local SSH connection successful", "action": ""}
331
+ console.print(Panel("✅ Local SSH connection works\n✅ SSH server is functional", title="[bold green]OK[/bold green]", border_style="green"))
332
+ else:
333
+ error_output = ssh_test.stderr
334
+ results["local_ssh_test"] = {"status": "warning", "message": f"Local SSH test failed: {error_output[:100]}", "action": "Check SSH keys and configuration"}
335
+ console.print(Panel(f"⚠️ Local SSH test failed\n💡 Error: {error_output[:200]}\n💡 This may be normal if key authentication is not set up for localhost", title="[bold yellow]Warning[/bold yellow]", border_style="yellow"))
336
+ except subprocess.TimeoutExpired:
337
+ results["local_ssh_test"] = {"status": "error", "message": "Local SSH connection timed out", "action": "SSH may be hanging or not responding"}
338
+ issues_found.append("SSH connection timeout")
339
+ console.print(Panel("❌ Local SSH connection timed out\n💡 SSH server may not be responding\n💡 Check: sudo systemctl status ssh", title="[bold red]Critical Issue[/bold red]", border_style="red"))
340
+ except FileNotFoundError:
341
+ results["local_ssh_test"] = {"status": "warning", "message": "ssh client not found", "action": "Install SSH client"}
342
+ console.print(Panel("⚠️ SSH client not installed\n💡 Install: sudo apt install openssh-client", title="[bold yellow]Warning[/bold yellow]", border_style="yellow"))
343
+ except Exception as test_error:
344
+ results["local_ssh_test"] = {"status": "warning", "message": f"Could not test SSH: {str(test_error)}", "action": ""}
345
+ console.print(Panel(f"⚠️ Could not test SSH connection: {str(test_error)}", title="[bold yellow]Warning[/bold yellow]", border_style="yellow"))
346
+
288
347
  console.print(Panel("📊 DIAGNOSTIC SUMMARY", box=box.DOUBLE_EDGE, title_align="left"))
289
348
 
290
349
  if issues_found:
@@ -292,6 +351,39 @@ def ssh_debug_linux() -> dict[str, dict[str, str | bool]]:
292
351
  else:
293
352
  console.print(Panel("✅ No critical issues detected\n\nIf you still cannot connect:\n• Check client-side configuration\n• Verify network connectivity\n• Ensure correct username and hostname\n• Check if public key is correctly added to authorized_keys", title="[bold green]All Checks Passed[/bold green]", border_style="green"))
294
353
 
354
+ console.print(Panel("🔗 CONNECTION INFORMATION", box=box.DOUBLE_EDGE, title_align="left"))
355
+
356
+ try:
357
+ current_user = os.environ.get("USER", os.environ.get("USERNAME", "unknown"))
358
+ hostname_result = subprocess.run(["hostname"], capture_output=True, text=True, check=False)
359
+ hostname = hostname_result.stdout.strip() if hostname_result.returncode == 0 else "unknown"
360
+
361
+ ip_addr_result = subprocess.run(["ip", "addr", "show"], capture_output=True, text=True, check=False)
362
+ connection_ips: list[str] = []
363
+ if ip_addr_result.returncode == 0:
364
+ import re
365
+ inet_pattern = re.compile(r'inet\s+(\d+\.\d+\.\d+\.\d+)/\d+.*scope\s+global')
366
+ connection_ips = inet_pattern.findall(ip_addr_result.stdout)
367
+
368
+ connection_info = f"👤 Username: {current_user}\n🖥️ Hostname: {hostname}\n🔌 SSH Port: {ssh_port}\n"
369
+
370
+ if connection_ips:
371
+ connection_info += "\n🌐 This machine can be accessed via SSH from other machines on the same network using:\n\n"
372
+ for ip in connection_ips:
373
+ connection_info += f" ssh {current_user}@{ip}\n"
374
+ if ssh_port != "22":
375
+ connection_info += f"\n (Port {ssh_port} should be used: ssh -p {ssh_port} {current_user}@<IP>)\n"
376
+ else:
377
+ connection_info += "\n⚠️ No network IP addresses found - this machine may not be reachable from the network"
378
+
379
+ connection_info += "\n\n💡 From another machine on the same network, use one of the commands above"
380
+ connection_info += "\n💡 Ensure your public key is in ~/.ssh/authorized_keys on this machine"
381
+ connection_info += "\n💡 Or use password authentication if enabled in sshd_config"
382
+
383
+ console.print(Panel(connection_info, title="[bold cyan]SSH Connection Details[/bold cyan]", border_style="cyan"))
384
+ except Exception as conn_error:
385
+ console.print(Panel(f"⚠️ Could not gather connection information: {str(conn_error)}", title="[bold yellow]Connection Info[/bold yellow]", border_style="yellow"))
386
+
295
387
  return results
296
388
 
297
389
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: machineconfig
3
- Version: 5.79
3
+ Version: 5.82
4
4
  Summary: Dotfiles management package
5
5
  Author-email: Alex Al-Saffar <programmer@usa.com>
6
6
  License: Apache 2.0
@@ -177,7 +177,7 @@ machineconfig/scripts/python/devops_helpers/__init__.py,sha256=47DEQpj8HBSa-_TIm
177
177
  machineconfig/scripts/python/devops_helpers/cli_config.py,sha256=wnQyhN-LbuIpVKvZhOxv8_UR7cwFTlKpZMqL3Ydi3Zo,5332
178
178
  machineconfig/scripts/python/devops_helpers/cli_config_dotfile.py,sha256=rjTys4FNf9_feP9flWM7Zvq17dxWmetSiGaHPxp25nk,2737
179
179
  machineconfig/scripts/python/devops_helpers/cli_data.py,sha256=kvJ7g2CccjjXIhCwdu_Vlif8JHC0qUoLjuGcTSqT-IU,514
180
- machineconfig/scripts/python/devops_helpers/cli_nw.py,sha256=ZEcF939Ggg26kr00lEY3xXmLNc3VqHcZm1aQ8R4zkf8,3852
180
+ machineconfig/scripts/python/devops_helpers/cli_nw.py,sha256=3KyzyoEyiLFrKxB5abkUq8UI3PoHWcI9PyczHf0YcSY,4023
181
181
  machineconfig/scripts/python/devops_helpers/cli_repos.py,sha256=HJH5ZBob_Uzhc3fDgG9riOeW6YEJt88xTjQYcEUPmUY,12015
182
182
  machineconfig/scripts/python/devops_helpers/cli_self.py,sha256=9ie3qtEKcUSDwi7rkwBbWCXZoYsk6wpYXEVIC4wlBIg,4531
183
183
  machineconfig/scripts/python/devops_helpers/cli_share_server.py,sha256=285OzxttCx7YsrpOkaapMKP1eVGHmG5TkkaSQnY7i3c,3976
@@ -234,7 +234,7 @@ machineconfig/scripts/python/nw/mount_nw_drive.py,sha256=iru6AtnTyvyuk6WxlK5R4lD
234
234
  machineconfig/scripts/python/nw/mount_smb,sha256=7UN5EP1kuxYL_-CnyaH4f9Wuu2CgALDZpJ0mPcdvCiY,94
235
235
  machineconfig/scripts/python/nw/mount_ssh.py,sha256=qt0P4T4pheszexBxaDeLVrGdLIVRoOc-UdfYv5r0OLY,2587
236
236
  machineconfig/scripts/python/nw/onetimeshare.py,sha256=xRd8by6qUm-od2Umty2MYsXyJwzXw-CBTd7VellNaKY,2498
237
- machineconfig/scripts/python/nw/ssh_debug_linux.py,sha256=LAKWq8rMWauvVk4_ap38SjZCIqPFaREjheJ84424Ss0,23012
237
+ machineconfig/scripts/python/nw/ssh_debug_linux.py,sha256=VSFhyzYQeLIoSwsUFJFW1Wc89DinrpZ_YxyYB2Ndy-4,30966
238
238
  machineconfig/scripts/python/nw/wifi_conn.py,sha256=4GdLhgma9GRmZ6OFg3oxOX-qY3sr45njPckozlpM_A0,15566
239
239
  machineconfig/scripts/python/nw/wsl_windows_transfer.py,sha256=1ab9l-8MtAxofW5nGH9G2-BjlszaiLETu6WBECcNNhA,3546
240
240
  machineconfig/scripts/python/repos_helpers/action.py,sha256=t6x9K43Uy7r5aRpdODfsN-5UoMrYXEG2cVw-Y8l9prw,14847
@@ -420,8 +420,8 @@ machineconfig/utils/schemas/installer/installer_types.py,sha256=QClRY61QaduBPJoS
420
420
  machineconfig/utils/schemas/layouts/layout_types.py,sha256=TcqlZdGVoH8htG5fHn1KWXhRdPueAcoyApppZsPAPto,2020
421
421
  machineconfig/utils/schemas/repos/repos_types.py,sha256=ECVr-3IVIo8yjmYmVXX2mnDDN1SLSwvQIhx4KDDQHBQ,405
422
422
  machineconfig/utils/ssh_utils/utils.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
423
- machineconfig-5.79.dist-info/METADATA,sha256=nOt7kAUNY1UoJ379exFvm1NOTHhm86l3arImwE_5vug,3013
424
- machineconfig-5.79.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
425
- machineconfig-5.79.dist-info/entry_points.txt,sha256=M0jwN_brZdXWhmNVeXLvdKxfkv8WhhXFZYcuKBA9qnk,418
426
- machineconfig-5.79.dist-info/top_level.txt,sha256=porRtB8qms8fOIUJgK-tO83_FeH6Bpe12oUVC670teA,14
427
- machineconfig-5.79.dist-info/RECORD,,
423
+ machineconfig-5.82.dist-info/METADATA,sha256=W-g65cG_kSWDmbuD43W0cu4-MJ6wsPuWI5WwEqKYdMM,3013
424
+ machineconfig-5.82.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
425
+ machineconfig-5.82.dist-info/entry_points.txt,sha256=M0jwN_brZdXWhmNVeXLvdKxfkv8WhhXFZYcuKBA9qnk,418
426
+ machineconfig-5.82.dist-info/top_level.txt,sha256=porRtB8qms8fOIUJgK-tO83_FeH6Bpe12oUVC670teA,14
427
+ machineconfig-5.82.dist-info/RECORD,,