同步移动端工程、设备控制改进与发布资料
This commit is contained in:
@@ -0,0 +1,64 @@
|
||||
"""Private, pinned SSH access for this workspace; never expose credential values."""
|
||||
from __future__ import annotations
|
||||
|
||||
import importlib.util
|
||||
import os
|
||||
from pathlib import Path
|
||||
import re
|
||||
|
||||
import paramiko
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[3]
|
||||
|
||||
|
||||
def connect():
|
||||
gate_path = ROOT / "测试相关资料/核桃派的用户名和密码和ip/prepare_credentials.py"
|
||||
spec = importlib.util.spec_from_file_location("qms_credentials", gate_path)
|
||||
gate = importlib.util.module_from_spec(spec)
|
||||
spec.loader.exec_module(gate)
|
||||
if not gate.ensure_credentials(gate_path.parent):
|
||||
raise RuntimeError("设备凭据门禁未通过")
|
||||
fields = gate._parse_fields(gate_path.with_name(gate.PRIVATE_NAME))
|
||||
host = fields["IP"].strip()
|
||||
port_match = re.search(r"(?:^|\s)-p\s+(\d+)", fields["SSH"])
|
||||
port = int(port_match.group(1)) if port_match else 22
|
||||
trust = Path.home() / ".codex-tools/tmp/qms-mobile-known_hosts"
|
||||
trust.parent.mkdir(parents=True, exist_ok=True)
|
||||
client = paramiko.SSHClient()
|
||||
if trust.exists():
|
||||
client.load_host_keys(str(trust))
|
||||
# First-use trust is pinned in a private local store. Changed keys are
|
||||
# rejected by Paramiko before this policy can be invoked.
|
||||
class PinFirstUse(paramiko.MissingHostKeyPolicy):
|
||||
def missing_host_key(self, ssh, hostname, key):
|
||||
ssh.get_host_keys().add(hostname, key.get_name(), key)
|
||||
ssh.save_host_keys(str(trust))
|
||||
client.set_missing_host_key_policy(PinFirstUse())
|
||||
try:
|
||||
client.connect(host, port=port, username=fields["用户名"], password=fields["密码"],
|
||||
look_for_keys=False, allow_agent=False, timeout=10,
|
||||
banner_timeout=10, auth_timeout=10)
|
||||
except Exception:
|
||||
client.close()
|
||||
raise RuntimeError("SSH 连接或主机密钥检查失败;未输出凭据") from None
|
||||
return client, fields
|
||||
|
||||
|
||||
def redact(text, fields):
|
||||
values = sorted((v for v in fields.values() if len(v) >= 4), key=len, reverse=True)
|
||||
for value in values:
|
||||
text = text.replace(value, "[private]")
|
||||
return text
|
||||
|
||||
|
||||
def execute(client, command, *, password=None, timeout=30):
|
||||
if password is not None:
|
||||
import shlex
|
||||
command = "sudo -S -p '' -- sh -c " + shlex.quote(command)
|
||||
stdin, stdout, stderr = client.exec_command(command, timeout=timeout)
|
||||
if password is not None:
|
||||
stdin.write(password + "\n")
|
||||
stdin.flush()
|
||||
out, err = stdout.read().decode("utf-8", "replace"), stderr.read().decode("utf-8", "replace")
|
||||
return stdout.channel.recv_exit_status(), out, err
|
||||
Reference in New Issue
Block a user