fix(security): authenticate VNC/terminal WebSockets and harden SSH/config
Some checks failed
Backend Tests / pytest (Python 3.12) (push) Failing after 46s
Some checks failed
Backend Tests / pytest (Python 3.12) (push) Failing after 46s
Critical security and robustness fixes from a code audit: - WS terminal/VNC now require a JWT (?token=), validate the session, vms.console permission and VM ownership before bridging to Proxmox (previously the LXC terminal gave unauthenticated root shell access). Frontend ConsolePage passes the token in both WS URLs. - Fix SSH fallback for `pvecm delnode`: SSHClient now supports password auth (it previously crashed with TypeError); ProxmoxClient stores the password for SSH fallbacks and the host port suffix is stripped. - Add production startup warnings for default ADMIN_PASSWORD and wildcard CORS_ORIGINS. - dashboard: use tz-aware utcnow() instead of naive datetime.utcnow(). - crypto: narrow decrypt_value except to InvalidToken and log failures. - ssh_client: guard the shared connection cache with a lock; make unknown-host-key rejection opt-in via SSH_REJECT_UNKNOWN_HOSTS. - logging: send loguru console output to stderr instead of stdout. - Sync version fallback to 1.5.1; remove one-off refactor scripts. - Add CODE_REVIEW.md audit report. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -101,6 +101,8 @@ class ProxmoxClient(VmMixin, LxcMixin, ClusterMixin, StorageMixin, NetworkMixin,
|
||||
self.host = host
|
||||
self.user = user
|
||||
self.timeout = timeout
|
||||
# Stored for SSH fallbacks (e.g. pvecm delnode) that need root password auth
|
||||
self._password = password
|
||||
# Улучшенный ключ кеша - включаем token_name для уникальности
|
||||
self.connection_key = f"{host}:{user}:{token_name or 'password'}"
|
||||
self.proxmox = None
|
||||
|
||||
@@ -286,8 +286,10 @@ class ClusterMixin:
|
||||
def _delete_cluster_node_via_ssh(self, node_name: str) -> Dict:
|
||||
"""SSH fallback для удаления ноды через pvecm delnode"""
|
||||
from app.ssh_client import SSHClient
|
||||
# self.host may carry an API port suffix (e.g. "1.2.3.4:8006"); SSH needs the bare host.
|
||||
ssh_host = self.host.split(':')[0] if self.host else self.host
|
||||
ssh = SSHClient(
|
||||
hostname=self.host,
|
||||
hostname=ssh_host,
|
||||
username='root',
|
||||
password=getattr(self, '_password', None),
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user