2022-02-28 05:02:26 +01:00
|
|
|
from typing import Optional
|
2021-10-15 22:52:13 +02:00
|
|
|
import logging
|
|
|
|
import os
|
|
|
|
import pathlib
|
2021-08-05 20:26:48 +02:00
|
|
|
import click
|
2022-02-28 05:02:26 +01:00
|
|
|
|
2022-10-08 04:04:27 +02:00
|
|
|
from config.state import config
|
2021-10-15 22:52:13 +02:00
|
|
|
from constants import SSH_COMMON_OPTIONS, SSH_DEFAULT_HOST, SSH_DEFAULT_PORT
|
2022-08-15 17:41:23 +02:00
|
|
|
from exec.cmd import run_cmd
|
2022-08-20 02:24:17 +02:00
|
|
|
from wrapper import check_programs_wrap
|
2021-08-05 20:26:48 +02:00
|
|
|
|
|
|
|
|
|
|
|
@click.command(name='ssh')
|
2022-02-28 05:02:26 +01:00
|
|
|
@click.argument('cmd', nargs=-1)
|
|
|
|
@click.option('--user', '-u', help='the SSH username', default=None)
|
|
|
|
@click.option('--host', '-h', help='the SSH host', default=SSH_DEFAULT_HOST)
|
|
|
|
@click.option('--port', '-p', help='the SSH port', type=int, default=SSH_DEFAULT_PORT)
|
|
|
|
def cmd_ssh(cmd: list[str], user: str, host: str, port: int):
|
|
|
|
"""Establish SSH connection to device"""
|
2022-08-16 15:50:14 +02:00
|
|
|
run_ssh_command(list(cmd), user=user, host=host, port=port, alloc_tty=True)
|
2021-10-01 12:31:08 +02:00
|
|
|
|
|
|
|
|
2022-08-11 06:23:06 +02:00
|
|
|
def run_ssh_command(cmd: list[str] = [],
|
|
|
|
user: Optional[str] = None,
|
|
|
|
host: str = SSH_DEFAULT_HOST,
|
|
|
|
port: int = SSH_DEFAULT_PORT,
|
2022-08-16 15:50:14 +02:00
|
|
|
alloc_tty: bool = True):
|
2022-08-20 02:24:17 +02:00
|
|
|
check_programs_wrap(['ssh'])
|
2021-10-15 22:52:13 +02:00
|
|
|
if not user:
|
|
|
|
user = config.get_profile()['username']
|
|
|
|
keys = find_ssh_keys()
|
2022-02-28 05:02:26 +01:00
|
|
|
extra_args = []
|
2021-10-15 22:52:13 +02:00
|
|
|
if len(keys) > 0:
|
2022-02-28 05:02:26 +01:00
|
|
|
extra_args += ['-i', keys[0]]
|
2022-08-27 16:48:50 +02:00
|
|
|
if config.runtime.verbose:
|
2022-02-28 05:02:26 +01:00
|
|
|
extra_args += ['-v']
|
2022-08-11 06:23:06 +02:00
|
|
|
if alloc_tty:
|
|
|
|
extra_args += ['-t']
|
2022-08-16 15:50:14 +02:00
|
|
|
hoststr = f'{(user + "@") if user else ""}{host}'
|
|
|
|
logging.info(f'Opening SSH connection to {hoststr} ({port})')
|
|
|
|
logging.debug(f"ssh: trying to run {cmd} on {hoststr}")
|
2022-08-11 06:23:06 +02:00
|
|
|
full_cmd = [
|
2021-08-08 18:32:42 +02:00
|
|
|
'ssh',
|
2022-02-28 05:02:26 +01:00
|
|
|
] + extra_args + SSH_COMMON_OPTIONS + [
|
2021-09-09 20:23:23 +02:00
|
|
|
'-p',
|
|
|
|
str(port),
|
2022-08-16 15:50:14 +02:00
|
|
|
hoststr,
|
2021-09-09 20:23:23 +02:00
|
|
|
'--',
|
2022-08-11 06:23:06 +02:00
|
|
|
] + cmd
|
|
|
|
logging.debug(f"running cmd: {full_cmd}")
|
2022-08-15 06:12:27 +02:00
|
|
|
return run_cmd(full_cmd)
|
2021-10-15 22:52:13 +02:00
|
|
|
|
|
|
|
|
|
|
|
def scp_put_files(src: list[str], dst: str, user: str = None, host: str = SSH_DEFAULT_HOST, port: int = SSH_DEFAULT_PORT):
|
2022-08-20 02:24:17 +02:00
|
|
|
check_programs_wrap(['scp'])
|
2021-10-15 22:52:13 +02:00
|
|
|
if not user:
|
|
|
|
user = config.get_profile()['username']
|
|
|
|
keys = find_ssh_keys()
|
|
|
|
key_args = []
|
|
|
|
if len(keys) > 0:
|
|
|
|
key_args = ['-i', keys[0]]
|
2022-08-11 06:23:06 +02:00
|
|
|
cmd = [
|
2021-10-15 22:52:13 +02:00
|
|
|
'scp',
|
|
|
|
] + key_args + SSH_COMMON_OPTIONS + [
|
|
|
|
'-P',
|
|
|
|
str(port),
|
|
|
|
] + src + [
|
|
|
|
f'{user}@{host}:{dst}',
|
2022-08-11 06:23:06 +02:00
|
|
|
]
|
|
|
|
logging.info(f"Copying files to {user}@{host}:{dst}:\n{src}")
|
|
|
|
logging.debug(f"running cmd: {cmd}")
|
2022-08-15 06:12:27 +02:00
|
|
|
return run_cmd(cmd)
|
2021-10-15 22:52:13 +02:00
|
|
|
|
|
|
|
|
|
|
|
def find_ssh_keys():
|
|
|
|
dir = os.path.join(pathlib.Path.home(), '.ssh')
|
|
|
|
if not os.path.exists(dir):
|
|
|
|
return []
|
|
|
|
keys = []
|
|
|
|
for file in os.listdir(dir):
|
|
|
|
if file.startswith('id_') and not file.endswith('.pub'):
|
|
|
|
keys.append(os.path.join(dir, file))
|
|
|
|
return keys
|
|
|
|
|
|
|
|
|
|
|
|
def copy_ssh_keys(root_dir: str, user: str):
|
2022-08-20 02:24:17 +02:00
|
|
|
check_programs_wrap(['ssh-keygen'])
|
2021-10-15 22:52:13 +02:00
|
|
|
authorized_keys_file = os.path.join(
|
|
|
|
root_dir,
|
|
|
|
'home',
|
|
|
|
user,
|
|
|
|
'.ssh',
|
|
|
|
'authorized_keys',
|
|
|
|
)
|
|
|
|
if os.path.exists(authorized_keys_file):
|
|
|
|
os.unlink(authorized_keys_file)
|
|
|
|
|
|
|
|
keys = find_ssh_keys()
|
|
|
|
if len(keys) == 0:
|
|
|
|
logging.info("Could not find any ssh key to copy")
|
|
|
|
create = click.confirm("Do you want me to generate an ssh key for you?", True)
|
|
|
|
if not create:
|
|
|
|
return
|
2022-08-15 06:12:27 +02:00
|
|
|
result = run_cmd([
|
2021-10-15 22:52:13 +02:00
|
|
|
'ssh-keygen',
|
|
|
|
'-f',
|
|
|
|
os.path.join(pathlib.Path.home(), '.ssh', 'id_ed25519_kupfer'),
|
|
|
|
'-t',
|
|
|
|
'ed25519',
|
|
|
|
'-C',
|
|
|
|
'kupfer',
|
|
|
|
'-N',
|
|
|
|
'',
|
|
|
|
])
|
2022-08-15 06:12:27 +02:00
|
|
|
if result.returncode != 0: # type: ignore
|
2021-10-15 22:52:13 +02:00
|
|
|
logging.fatal("Failed to generate ssh key")
|
|
|
|
keys = find_ssh_keys()
|
|
|
|
|
|
|
|
ssh_dir = os.path.join(root_dir, 'home', user, '.ssh')
|
|
|
|
if not os.path.exists(ssh_dir):
|
2022-08-16 00:09:23 +02:00
|
|
|
os.makedirs(ssh_dir, exist_ok=True, mode=0o700)
|
2021-10-15 22:52:13 +02:00
|
|
|
|
|
|
|
with open(authorized_keys_file, 'a') as authorized_keys:
|
|
|
|
for key in keys:
|
2021-10-25 20:47:17 +02:00
|
|
|
pub = f'{key}.pub'
|
2022-08-16 00:09:23 +02:00
|
|
|
if not os.path.exists(pub):
|
2021-10-25 20:47:17 +02:00
|
|
|
logging.debug(f'Skipping key {key}: {pub} not found')
|
|
|
|
continue
|
|
|
|
with open(pub, 'r') as file:
|
2021-10-15 22:52:13 +02:00
|
|
|
authorized_keys.write(file.read())
|