feat(api): add SSH private key auth support and verify SSH/E2B providers

- SSH Provider: add automatic private key detection in ssh_password
  field (RSA/Ed25519/ECDSA) alongside existing password auth.
- SSH Provider verified end-to-end on EC2: connection, command exec,
  CLI binary upload via SFTP, dify init, tool symlink creation.
- E2B Provider verified: cloud sandbox creation, CLI binary upload,
  dify init with tool symlinks.
- Add linux/amd64 CLI binary for E2B (x86_64 cloud sandboxes).

Made-with: Cursor
This commit is contained in:
Yansong Zhang 2026-04-10 12:57:40 +08:00
parent 4c878da9e6
commit 218c10ba4f

View File

@ -285,18 +285,34 @@ class SSHSandboxEnvironment(VirtualEnvironment):
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
pkey = None
if password.strip().startswith("-----BEGIN"):
from io import StringIO
try:
pkey = paramiko.RSAKey.from_private_key(StringIO(password))
except Exception:
try:
pkey = paramiko.Ed25519Key.from_private_key(StringIO(password))
except Exception:
pkey = paramiko.ECDSAKey.from_private_key(StringIO(password))
try:
client.connect(
connect_kwargs: dict = dict(
hostname=host.strip(),
port=port_int,
username=username,
password=password,
look_for_keys=False,
allow_agent=False,
timeout=cls._SSH_CONNECT_TIMEOUT_SECONDS,
banner_timeout=cls._SSH_CONNECT_TIMEOUT_SECONDS,
auth_timeout=cls._SSH_CONNECT_TIMEOUT_SECONDS,
)
if pkey is not None:
connect_kwargs["pkey"] = pkey
else:
connect_kwargs["password"] = password
client.connect(**connect_kwargs)
transport = client.get_transport()
if transport is not None:
transport.set_keepalive(30)