import upstream GUKO 2026-06-23

This commit is contained in:
OpenClaw
2026-06-23 00:44:35 +00:00
commit 0e79f74184
30 changed files with 6419 additions and 0 deletions

109
auth.py Normal file
View File

@@ -0,0 +1,109 @@
import os
import shlex
from pathlib import Path
ROOT = Path(__file__).resolve().parent
DEFAULT_KEY = os.environ.get('GUKO_DEFAULT_KEY') or os.environ.get('VPSPILOT_DEFAULT_KEY') or os.environ.get('JIAOOPS_DEFAULT_KEY', '/data/keys/id_ed25519')
DEFAULT_PORT = int(os.environ.get('GUKO_DEFAULT_PORT') or os.environ.get('VPSPILOT_DEFAULT_PORT') or os.environ.get('JIAOOPS_DEFAULT_PORT', '22'))
DEFAULT_USER = os.environ.get('GUKO_DEFAULT_USER') or os.environ.get('VPSPILOT_DEFAULT_USER') or os.environ.get('JIAOOPS_DEFAULT_USER', 'root')
def inventory_defaults(inv: dict | None = None) -> dict:
inv = inv or {}
defaults = inv.get('defaults') or {}
ssh = defaults.get('ssh') or defaults
return {
'user': ssh.get('user') or defaults.get('user') or DEFAULT_USER,
'port': ssh.get('port') or defaults.get('port') or DEFAULT_PORT,
'key': ssh.get('key') or defaults.get('key') or DEFAULT_KEY,
'password': ssh.get('password') or defaults.get('password'),
'auth': ssh.get('auth') or defaults.get('auth'),
}
def resolve_ssh(server: dict, inv: dict | None = None) -> dict:
"""Resolve SSH settings with compatibility for old flat server entries.
Supported server formats:
{"host":"1.2.3.4", "port":22, "user":"root", "key":"/path/key"}
{"host":"1.2.3.4", "ssh":{"port":22, "user":"root", "key":"/path/key"}}
{"host":"1.2.3.4", "auth":"password", "password":"secret"}
{"host":"1.2.3.4", "ssh":{"auth":"password", "password":"secret"}}
"""
defaults = inventory_defaults(inv)
ssh = server.get('ssh') or {}
explicit_key = ssh.get('key') or server.get('key')
cfg = {
'host': ssh.get('host') or server.get('host'),
'user': ssh.get('user') or server.get('user') or defaults['user'],
'port': ssh.get('port') or server.get('port') or defaults['port'],
'key': explicit_key or defaults.get('key'),
'password': ssh.get('password') or server.get('password') or defaults.get('password'),
'auth': ssh.get('auth') or server.get('auth') or defaults.get('auth'),
}
cfg['port'] = int(cfg['port'])
if not cfg['auth']:
cfg['auth'] = 'password' if cfg.get('password') else 'key'
if cfg['auth'] == 'password' and not explicit_key:
cfg['key'] = None
if cfg.get('key'):
cfg['key'] = os.path.expanduser(str(cfg['key']))
return cfg
def _base_ssh_options(cfg: dict, *, tty=False, batch=True) -> list[str]:
args = [
'-o', f"BatchMode={'yes' if batch else 'no'}",
'-o', 'ConnectTimeout=10',
'-o', 'ServerAliveInterval=30',
'-o', 'ServerAliveCountMax=6',
'-o', 'StrictHostKeyChecking=accept-new',
'-p', str(cfg['port']),
]
if cfg.get('key'):
args += ['-i', str(cfg['key'])]
if tty:
args.append('-tt')
return args
def ssh_args(server: dict, remote: str, *, tty=False, inv: dict | None = None) -> list[str]:
cfg = resolve_ssh(server, inv)
if not cfg.get('host'):
raise ValueError('missing ssh host')
batch = not (cfg.get('auth') == 'password' and cfg.get('password'))
args = ['ssh'] + _base_ssh_options(cfg, tty=tty, batch=batch)
args += [f"{cfg['user']}@{cfg['host']}", remote]
if cfg.get('auth') == 'password' and cfg.get('password'):
return ['sshpass', '-e'] + args
return args
def scp_from_args(server: dict, remote_path: str, local_path: str, *, inv: dict | None = None) -> list[str]:
cfg = resolve_ssh(server, inv)
if not cfg.get('host'):
raise ValueError('missing ssh host')
batch = not (cfg.get('auth') == 'password' and cfg.get('password'))
args = [
'scp',
'-o', f"BatchMode={'yes' if batch else 'no'}",
'-o', 'ConnectTimeout=10',
'-o', 'StrictHostKeyChecking=accept-new',
'-P', str(cfg['port']),
]
if cfg.get('key'):
args += ['-i', str(cfg['key'])]
args += [f"{cfg['user']}@{cfg['host']}:{remote_path}", local_path]
if cfg.get('auth') == 'password' and cfg.get('password'):
return ['sshpass', '-e'] + args
return args
def ssh_display(server: dict, inv: dict | None = None) -> str:
cfg = resolve_ssh(server, inv)
auth = 'password' if cfg.get('auth') == 'password' else 'key'
return f"{cfg.get('user')}@{cfg.get('host')}:{cfg.get('port')} ({auth})"
def shell_join(args: list[str]) -> str:
return ' '.join(shlex.quote(str(x)) for x in args)