|
19 | 19 |
|
20 | 20 | from argparse import ArgumentParser, Namespace
|
21 | 21 | from pathlib import Path
|
| 22 | +from pwd import getpwall |
22 | 23 | from shutil import copy, chown, rmtree, copytree, disk_usage
|
23 | 24 | from glob import glob
|
24 | 25 | from sys import exit
|
@@ -715,6 +716,20 @@ def copy_ssh_host_keys() -> bool:
|
715 | 716 | return False
|
716 | 717 |
|
717 | 718 |
|
| 719 | +def copy_ssh_known_hosts() -> bool: |
| 720 | + """Ask user to copy SSH `known_hosts` files |
| 721 | +
|
| 722 | + Returns: |
| 723 | + bool: user's decision |
| 724 | + """ |
| 725 | + known_hosts_files = get_known_hosts_files() |
| 726 | + msg = ( |
| 727 | + 'Would you like to save the SSH known hosts (fingerprints) ' |
| 728 | + 'from your current configuration?' |
| 729 | + ) |
| 730 | + return known_hosts_files and ask_yes_no(msg, default=True) |
| 731 | + |
| 732 | + |
718 | 733 | def console_hint() -> str:
|
719 | 734 | pid = getppid() if 'SUDO_USER' in environ else getpid()
|
720 | 735 | try:
|
@@ -1010,6 +1025,41 @@ def install_image() -> None:
|
1010 | 1025 | exit(1)
|
1011 | 1026 |
|
1012 | 1027 |
|
| 1028 | +def get_known_hosts_files() -> list: |
| 1029 | + """Collect all existing `known_hosts` files for root and users under /home""" |
| 1030 | + |
| 1031 | + files = [] |
| 1032 | + |
| 1033 | + # for root |
| 1034 | + base_files = ('/root/.ssh/known_hosts', '/etc/ssh/ssh_known_hosts') |
| 1035 | + for file_path in base_files: |
| 1036 | + root_known_hosts = Path(file_path) |
| 1037 | + if root_known_hosts.exists(): |
| 1038 | + files.append(root_known_hosts) |
| 1039 | + |
| 1040 | + # for each non-system user |
| 1041 | + for user in getpwall(): |
| 1042 | + home_dir = Path(user.pw_dir) |
| 1043 | + # skip system users |
| 1044 | + if home_dir.exists() and home_dir.as_posix().startswith('/home'): |
| 1045 | + known_hosts = home_dir / '.ssh' / 'known_hosts' |
| 1046 | + if known_hosts.exists(): |
| 1047 | + files.append(known_hosts) |
| 1048 | + |
| 1049 | + return files |
| 1050 | + |
| 1051 | + |
| 1052 | +def migrate_known_hosts(target_dir: str): |
| 1053 | + """Copy `known_hosts` for root and all users to the new image directory""" |
| 1054 | + |
| 1055 | + known_hosts_files = get_known_hosts_files() |
| 1056 | + for known_hosts_file in known_hosts_files: |
| 1057 | + # copy file to target directory |
| 1058 | + target_known_hosts = Path(f'{target_dir}{known_hosts_file}') |
| 1059 | + target_known_hosts.parent.mkdir(parents=True, exist_ok=True) |
| 1060 | + copy(known_hosts_file, target_known_hosts) |
| 1061 | + |
| 1062 | + |
1013 | 1063 | @compat.grub_cfg_update
|
1014 | 1064 | def add_image(image_path: str, vrf: str = None, username: str = '',
|
1015 | 1065 | password: str = '', no_prompt: bool = False, force: bool = False) -> None:
|
@@ -1115,6 +1165,11 @@ def add_image(image_path: str, vrf: str = None, username: str = '',
|
1115 | 1165 | for host_key in host_keys:
|
1116 | 1166 | copy(host_key, target_ssh_dir)
|
1117 | 1167 |
|
| 1168 | + target_ssh_known_hosts_dir: str = f'{root_dir}/boot/{image_name}/rw' |
| 1169 | + if no_prompt or copy_ssh_known_hosts(): |
| 1170 | + print('Copying SSH known hosts') |
| 1171 | + migrate_known_hosts(target_ssh_known_hosts_dir) |
| 1172 | + |
1118 | 1173 | # copy system image and kernel files
|
1119 | 1174 | print('Copying system image files')
|
1120 | 1175 | for file in Path(f'{DIR_ISO_MOUNT}/live').iterdir():
|
|
0 commit comments