fix: ssh-copy-id interactive (capture=False) so password prompt visible; encrypted keys just warned, not source-server passphrase confusion; clear auth choice menu for target
This commit is contained in:
@@ -105,20 +105,21 @@ def generate_temp_keypair(host_label):
|
||||
|
||||
|
||||
def ssh_copy_id(host, user, port, pubkey_path):
|
||||
"""Копирует публичный ключ на target через ssh-copy-id или вручную."""
|
||||
"""Копирует публичный ключ на target через ssh-copy-id. Интерактивно, т.к. запрашивает пароль target."""
|
||||
if exists("ssh-copy-id"):
|
||||
info("Копируем публичный ключ через ssh-copy-id ...")
|
||||
# Добавляем SSH опции чтобы избежать зависания
|
||||
warn("⚠ Сейчас запустится ssh-copy-id — на target запросит ПАРОЛЬ. Введите его ниже ↓")
|
||||
# Запускаем без capture_output, чтобы prompt пароля был виден пользователю
|
||||
r = run(
|
||||
f"ssh-copy-id -p {port} -o ConnectTimeout=10 -o StrictHostKeyChecking=accept-new -i '{pubkey_path}' {user}@{host}",
|
||||
f"ssh-copy-id -p {port} -o ConnectTimeout=30 -o StrictHostKeyChecking=accept-new -i '{pubkey_path}' {user}@{host}",
|
||||
check=False,
|
||||
timeout=60
|
||||
capture=False,
|
||||
timeout=120
|
||||
)
|
||||
if r.returncode == 0:
|
||||
success("Ключ добавлен на target через ssh-copy-id")
|
||||
return True
|
||||
else:
|
||||
warn(f"ssh-copy-id не удался: {r.stderr.strip()[:120]}")
|
||||
warn(f"ssh-copy-id не удался (код: {r.returncode})")
|
||||
return False
|
||||
|
||||
|
||||
@@ -218,28 +219,21 @@ def pick_or_setup_ssh_key(host, user, port):
|
||||
if working_key:
|
||||
return working_key["private"]
|
||||
|
||||
# 3. Проверить ключи С passphrase (если пользователь знает)
|
||||
# 3. Проверить ключи — если зашифрован и не подходит, просто сообщаем и идём дальше
|
||||
encrypted_count = 0
|
||||
for k in keys:
|
||||
label = os.path.basename(k["private"])
|
||||
# Проверим, не passphrase ли мешает
|
||||
ok, _, err = check_ssh_connectivity(host, user, port, key_path=k["private"])
|
||||
if not ok and ("passphrase" in err.lower() or "password" in err.lower()):
|
||||
if confirm(f"Ключ '{label}' зашифрован. Ввести passphrase и попробовать", default="y"):
|
||||
from core.color import prompt_password
|
||||
pw = prompt_password(f"Passphrase для {label}")
|
||||
if pw and try_key_with_passphrase(k["private"], pw):
|
||||
# После ssh-add ключ должен работать
|
||||
ok2, _, _ = check_ssh_connectivity(host, user, port, key_path=k["private"])
|
||||
if ok2:
|
||||
success(f"Ключ '{label}' разблокирован и работает!")
|
||||
return k["private"]
|
||||
else:
|
||||
warn(f"Passphrase введён, но ключ всё равно не подходит для {host}")
|
||||
warn(f" ! Ключ '{label}' зашифрован (passphrase). Пропускаем.")
|
||||
encrypted_count += 1
|
||||
if encrypted_count and not working_key:
|
||||
info(f"Все найденные ключи зашифрованы или не подходят для {host}.")
|
||||
|
||||
# 4. Ничего не работает — выбор метода
|
||||
print()
|
||||
info("Выберите способ подключения к target:")
|
||||
print(" 1 Пароль (sshpass) — ввести пароль прямо сейчас")
|
||||
print(" 1 Пароль (sshpass) — ввести пароль от target прямо сейчас")
|
||||
print(" 2 Сгенерировать временный ed25519 ключ — скрипт сам сделает ssh-copy-id")
|
||||
print(" 0 Отмена — передать архив вручную")
|
||||
choice = prompt("Ваш выбор", default="1").strip()
|
||||
|
||||
Reference in New Issue
Block a user