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):
|
def ssh_copy_id(host, user, port, pubkey_path):
|
||||||
"""Копирует публичный ключ на target через ssh-copy-id или вручную."""
|
"""Копирует публичный ключ на target через ssh-copy-id. Интерактивно, т.к. запрашивает пароль target."""
|
||||||
if exists("ssh-copy-id"):
|
if exists("ssh-copy-id"):
|
||||||
info("Копируем публичный ключ через ssh-copy-id ...")
|
warn("⚠ Сейчас запустится ssh-copy-id — на target запросит ПАРОЛЬ. Введите его ниже ↓")
|
||||||
# Добавляем SSH опции чтобы избежать зависания
|
# Запускаем без capture_output, чтобы prompt пароля был виден пользователю
|
||||||
r = run(
|
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,
|
check=False,
|
||||||
timeout=60
|
capture=False,
|
||||||
|
timeout=120
|
||||||
)
|
)
|
||||||
if r.returncode == 0:
|
if r.returncode == 0:
|
||||||
success("Ключ добавлен на target через ssh-copy-id")
|
success("Ключ добавлен на target через ssh-copy-id")
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
warn(f"ssh-copy-id не удался: {r.stderr.strip()[:120]}")
|
warn(f"ssh-copy-id не удался (код: {r.returncode})")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
@@ -218,28 +219,21 @@ def pick_or_setup_ssh_key(host, user, port):
|
|||||||
if working_key:
|
if working_key:
|
||||||
return working_key["private"]
|
return working_key["private"]
|
||||||
|
|
||||||
# 3. Проверить ключи С passphrase (если пользователь знает)
|
# 3. Проверить ключи — если зашифрован и не подходит, просто сообщаем и идём дальше
|
||||||
|
encrypted_count = 0
|
||||||
for k in keys:
|
for k in keys:
|
||||||
label = os.path.basename(k["private"])
|
label = os.path.basename(k["private"])
|
||||||
# Проверим, не passphrase ли мешает
|
|
||||||
ok, _, err = check_ssh_connectivity(host, user, port, key_path=k["private"])
|
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 not ok and ("passphrase" in err.lower() or "password" in err.lower()):
|
||||||
if confirm(f"Ключ '{label}' зашифрован. Ввести passphrase и попробовать", default="y"):
|
warn(f" ! Ключ '{label}' зашифрован (passphrase). Пропускаем.")
|
||||||
from core.color import prompt_password
|
encrypted_count += 1
|
||||||
pw = prompt_password(f"Passphrase для {label}")
|
if encrypted_count and not working_key:
|
||||||
if pw and try_key_with_passphrase(k["private"], pw):
|
info(f"Все найденные ключи зашифрованы или не подходят для {host}.")
|
||||||
# После 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}")
|
|
||||||
|
|
||||||
# 4. Ничего не работает — выбор метода
|
# 4. Ничего не работает — выбор метода
|
||||||
print()
|
print()
|
||||||
info("Выберите способ подключения к target:")
|
info("Выберите способ подключения к target:")
|
||||||
print(" 1 Пароль (sshpass) — ввести пароль прямо сейчас")
|
print(" 1 Пароль (sshpass) — ввести пароль от target прямо сейчас")
|
||||||
print(" 2 Сгенерировать временный ed25519 ключ — скрипт сам сделает ssh-copy-id")
|
print(" 2 Сгенерировать временный ed25519 ключ — скрипт сам сделает ssh-copy-id")
|
||||||
print(" 0 Отмена — передать архив вручную")
|
print(" 0 Отмена — передать архив вручную")
|
||||||
choice = prompt("Ваш выбор", default="1").strip()
|
choice = prompt("Ваш выбор", default="1").strip()
|
||||||
|
|||||||
Reference in New Issue
Block a user