def setup_user_keys(keys, username, options=None): # Make sure the users .ssh dir is setup accordingly (ssh_dir, pwent) = users_ssh_info(username) LOG.debug("ssh_dir " + str(ssh_dir)) homedir = pwent.pw_dir LOG.debug("homedir " + str(homedir)) util.ensure_dir(homedir, mode=0o750) util.chownbyid(homedir, pwent.pw_uid, pwent.pw_gid) util.ensure_dir(ssh_dir, mode=0o700) util.chownbyid(ssh_dir, pwent.pw_uid, pwent.pw_gid) # Turn the 'update' keys given into actual entries parser = AuthKeyLineParser() key_entries = [] for k in keys: key_entries.append(parser.parse(str(k), options=options)) # Extract the old and make the new (auth_key_fn, auth_key_entries) = extract_authorized_keys(username) LOG.debug("auth_key_fn " + str(auth_key_fn)) with util.SeLinuxGuard(ssh_dir, recursive=True): content = update_authorized_keys(auth_key_entries, key_entries) util.ensure_dir(os.path.dirname(auth_key_fn), mode=0o700) util.write_file(auth_key_fn, content, mode=0o600) util.chownbyid(auth_key_fn, pwent.pw_uid, pwent.pw_gid)
def extract_authorized_keys(username): (ssh_dir, pw_ent) = users_ssh_info(username) auth_key_fn = None with util.SeLinuxGuard(ssh_dir, recursive=True): try: # The 'AuthorizedKeysFile' may contain tokens # of the form %T which are substituted during connection set-up. # The following tokens are defined: %% is replaced by a literal # '%', %h is replaced by the home directory of the user being # authenticated and %u is replaced by the username of that user. ssh_cfg = parse_ssh_config_map(DEF_SSHD_CFG) auth_key_fn = ssh_cfg.get("authorizedkeysfile", '').strip() if not auth_key_fn: auth_key_fn = "%h/.ssh/authorized_keys" auth_key_fn = auth_key_fn.replace("%h", pw_ent.pw_dir) auth_key_fn = auth_key_fn.replace("%u", username) auth_key_fn = auth_key_fn.replace("%%", '%') if not auth_key_fn.startswith('/'): auth_key_fn = os.path.join(pw_ent.pw_dir, auth_key_fn) except (IOError, OSError): # Give up and use a default key filename auth_key_fn = os.path.join(ssh_dir, 'authorized_keys') util.logexc( LOG, "Failed extracting 'AuthorizedKeysFile' in ssh " "config from %r, using 'AuthorizedKeysFile' file " "%r instead", DEF_SSHD_CFG, auth_key_fn) return (auth_key_fn, parse_authorized_keys(auth_key_fn))
def extract_authorized_keys(username, sshd_cfg_file=DEF_SSHD_CFG): (ssh_dir, pw_ent) = users_ssh_info(username) default_authorizedkeys_file = os.path.join(ssh_dir, 'authorized_keys') auth_key_fns = [] with util.SeLinuxGuard(ssh_dir, recursive=True): try: ssh_cfg = parse_ssh_config_map(sshd_cfg_file) # Delphix: only extract keys from first path as the second path # contains cli keys that should not be manipulated by cloud-init. auth_key_fns = [ render_authorizedkeysfile_paths( ssh_cfg.get("authorizedkeysfile", "%h/.ssh/authorized_keys"), pw_ent.pw_dir, username)[0] ] except (IOError, OSError): # Give up and use a default key filename auth_key_fns = [default_authorizedkeys_file] util.logexc( LOG, "Failed extracting 'AuthorizedKeysFile' in SSH " "config from %r, using 'AuthorizedKeysFile' file " "%r instead", DEF_SSHD_CFG, auth_key_fns[0]) # always store all the keys in the user's private file return (default_authorizedkeys_file, parse_authorized_keys(auth_key_fns))
def extract_authorized_keys(username, sshd_cfg_file=DEF_SSHD_CFG): (ssh_dir, pw_ent) = users_ssh_info(username) default_authorizedkeys_file = os.path.join(ssh_dir, "authorized_keys") user_authorizedkeys_file = default_authorizedkeys_file auth_key_fns = [] with util.SeLinuxGuard(ssh_dir, recursive=True): try: ssh_cfg = parse_ssh_config_map(sshd_cfg_file) key_paths = ssh_cfg.get( "authorizedkeysfile", "%h/.ssh/authorized_keys" ) strictmodes = ssh_cfg.get("strictmodes", "yes") auth_key_fns = render_authorizedkeysfile_paths( key_paths, pw_ent.pw_dir, username ) except (IOError, OSError): # Give up and use a default key filename auth_key_fns[0] = default_authorizedkeys_file util.logexc( LOG, "Failed extracting 'AuthorizedKeysFile' in SSH " "config from %r, using 'AuthorizedKeysFile' file " "%r instead", DEF_SSHD_CFG, auth_key_fns[0], ) # check if one of the keys is the user's one and has the right permissions for key_path, auth_key_fn in zip(key_paths.split(), auth_key_fns): if any( [ "%u" in key_path, "%h" in key_path, auth_key_fn.startswith("{}/".format(pw_ent.pw_dir)), ] ): permissions_ok = check_create_path( username, auth_key_fn, strictmodes == "yes" ) if permissions_ok: user_authorizedkeys_file = auth_key_fn break if user_authorizedkeys_file != default_authorizedkeys_file: LOG.debug( "AuthorizedKeysFile has an user-specific authorized_keys, " "using %s", user_authorizedkeys_file, ) return ( user_authorizedkeys_file, parse_authorized_keys([user_authorizedkeys_file]), )
def test_restorecon_if_possible_is_called(self): """Make sure the selinux guard is called correctly.""" import_mock = self.mocker.replace(importer.import_module, passthrough=False) import_mock('selinux') fake_se = FakeSelinux('/etc/hosts') self.mocker.result(fake_se) self.mocker.replay() with util.SeLinuxGuard("/etc/hosts") as is_on: self.assertTrue(is_on) self.assertEqual(1, len(fake_se.restored)) self.assertEqual('/etc/hosts', fake_se.restored[0])
def setup_user_keys(keys, username, options=None): # Turn the 'update' keys given into actual entries parser = AuthKeyLineParser() key_entries = [] for k in keys: key_entries.append(parser.parse(str(k), options=options)) # Extract the old and make the new (auth_key_fn, auth_key_entries) = extract_authorized_keys(username) ssh_dir = os.path.dirname(auth_key_fn) with util.SeLinuxGuard(ssh_dir, recursive=True): content = update_authorized_keys(auth_key_entries, key_entries) util.write_file(auth_key_fn, content, preserve_mode=True)
def check_create_path(username, filename, strictmodes): user_pwent = users_ssh_info(username)[1] root_pwent = users_ssh_info("root")[1] try: # check the directories first directories = filename.split("/")[1:-1] # scan in order, from root to file name parent_folder = "" # this is to comply also with unit tests, and # strange home directories home_folder = os.path.dirname(user_pwent.pw_dir) for directory in directories: parent_folder += "/" + directory if home_folder.startswith(parent_folder): continue if not os.path.isdir(parent_folder): # directory does not exist, and permission so far are good: # create the directory, and make it accessible by everyone # but owned by root, as it might be used by many users. with util.SeLinuxGuard(parent_folder): os.makedirs(parent_folder, mode=0o755, exist_ok=True) util.chownbyid(parent_folder, root_pwent.pw_uid, root_pwent.pw_gid) permissions = check_permissions(username, parent_folder, filename, False, strictmodes) if not permissions: return False # check the file if not os.path.exists(filename): # if file does not exist: we need to create it, since the # folders at this point exist and have right permissions util.write_file(filename, '', mode=0o600, ensure_dir_exists=True) util.chownbyid(filename, user_pwent.pw_uid, user_pwent.pw_gid) permissions = check_permissions(username, filename, filename, True, strictmodes) if not permissions: return False except (IOError, OSError) as e: util.logexc(LOG, str(e)) return False return True
def test_restorecon_if_possible_is_called(self): """Make sure the selinux guard is called correctly.""" my_file = os.path.join(self.tmp, "my_file") with open(my_file, "w") as fp: fp.write("My Content") import_mock = self.mocker.replace(importer.import_module, passthrough=False) import_mock('selinux') fake_se = FakeSelinux(my_file) self.mocker.result(fake_se) self.mocker.replay() with util.SeLinuxGuard(my_file) as is_on: self.assertTrue(is_on) self.assertEqual(1, len(fake_se.restored)) self.assertEqual(my_file, fake_se.restored[0])
def test_restorecon_if_possible_is_called(self): """Make sure the selinux guard is called correctly.""" my_file = os.path.join(self.tmp, "my_file") with open(my_file, "w") as fp: fp.write("My Content") fake_se = FakeSelinux(my_file) with mock.patch.object(importer, 'import_module', return_value=fake_se) as mockobj: with util.SeLinuxGuard(my_file) as is_on: self.assertTrue(is_on) self.assertEqual(1, len(fake_se.restored)) self.assertEqual(my_file, fake_se.restored[0]) mockobj.assert_called_once_with('selinux')
def extract_authorized_keys(username): (ssh_dir, pw_ent) = users_ssh_info(username) auth_key_fn = None with util.SeLinuxGuard(ssh_dir, recursive=True): try: # The 'AuthorizedKeysFile' may contain tokens # of the form %T which are substituted during connection set-up. # The following tokens are defined: %% is replaced by a literal # '%', %h is replaced by the home directory of the user being # authenticated and %u is replaced by the username of that user. # Note that there may be multiple files defined, separated by # white space. If multiple files are detected, return the first # one. ssh_cfg = parse_ssh_config_map(DEF_SSHD_CFG) value = ssh_cfg.get("authorizedkeysfile", '').strip() if value: files = shlex.split(value) if len(files) == 1: auth_key_fn = files[0] elif len(files) > 1: auth_key_fn = files[0] LOG.debug( "Entry 'AuthorizedKeysFile' in ssh config " "defines multiple files. Using the first one: " "%r.", auth_key_fn) else: LOG.debug("Entry 'AuthorizedKeysFile' in ssh config " "has empty value. Using default file.") if not auth_key_fn: auth_key_fn = "%h/.ssh/authorized_keys" auth_key_fn = auth_key_fn.replace("%h", pw_ent.pw_dir) auth_key_fn = auth_key_fn.replace("%u", username) auth_key_fn = auth_key_fn.replace("%%", '%') if not auth_key_fn.startswith('/'): auth_key_fn = os.path.join(pw_ent.pw_dir, auth_key_fn) except (IOError, OSError, ValueError): # Give up and use a default key filename auth_key_fn = os.path.join(ssh_dir, 'authorized_keys') util.logexc( LOG, "Failed extracting 'AuthorizedKeysFile' in ssh " "config from %r, using 'AuthorizedKeysFile' file " "%r instead", DEF_SSHD_CFG, auth_key_fn) return (auth_key_fn, parse_authorized_keys(auth_key_fn))
def extract_authorized_keys(username, sshd_cfg_file=DEF_SSHD_CFG): (ssh_dir, pw_ent) = users_ssh_info(username) default_authorizedkeys_file = os.path.join(ssh_dir, 'authorized_keys') auth_key_fns = [] with util.SeLinuxGuard(ssh_dir, recursive=True): try: ssh_cfg = parse_ssh_config_map(sshd_cfg_file) auth_key_fns = render_authorizedkeysfile_paths( ssh_cfg.get("authorizedkeysfile", "%h/.ssh/authorized_keys"), pw_ent.pw_dir, username) except (IOError, OSError): # Give up and use a default key filename auth_key_fns[0] = default_authorizedkeys_file util.logexc(LOG, "Failed extracting 'AuthorizedKeysFile' in SSH " "config from %r, using 'AuthorizedKeysFile' file " "%r instead", DEF_SSHD_CFG, auth_key_fns[0]) # always store all the keys in the user's private file return (default_authorizedkeys_file, parse_authorized_keys(auth_key_fns))
def extract_authorized_keys(username, sshd_cfg_file=DEF_SSHD_CFG): (ssh_dir, pw_ent) = users_ssh_info(username) default_authorizedkeys_file = os.path.join(ssh_dir, 'authorized_keys') user_authorizedkeys_file = default_authorizedkeys_file auth_key_fns = [] with util.SeLinuxGuard(ssh_dir, recursive=True): try: ssh_cfg = parse_ssh_config_map(sshd_cfg_file) key_paths = ssh_cfg.get("authorizedkeysfile", "%h/.ssh/authorized_keys") auth_key_fns = render_authorizedkeysfile_paths( key_paths, pw_ent.pw_dir, username) except (IOError, OSError): # Give up and use a default key filename auth_key_fns[0] = default_authorizedkeys_file util.logexc( LOG, "Failed extracting 'AuthorizedKeysFile' in SSH " "config from %r, using 'AuthorizedKeysFile' file " "%r instead", DEF_SSHD_CFG, auth_key_fns[0]) # check if one of the keys is the user's one for key_path, auth_key_fn in zip(key_paths.split(), auth_key_fns): if any([ '%u' in key_path, '%h' in key_path, auth_key_fn.startswith('{}/'.format(pw_ent.pw_dir)) ]): user_authorizedkeys_file = auth_key_fn if user_authorizedkeys_file != default_authorizedkeys_file: LOG.debug( "AuthorizedKeysFile has an user-specific authorized_keys, " "using %s", user_authorizedkeys_file) # always store all the keys in the user's private file return (user_authorizedkeys_file, parse_authorized_keys(auth_key_fns))
def handle(_name, cfg, cloud, log, _args): # remove the static keys from the pristine image if cfg.get("ssh_deletekeys", True): key_pth = os.path.join("/etc/ssh/", "ssh_host_*key*") for f in glob.glob(key_pth): try: util.del_file(f) except Exception: util.logexc(log, "Failed deleting key file %s", f) if "ssh_keys" in cfg: # if there are keys in cloud-config, use them for (key, val) in cfg["ssh_keys"].items(): if key in CONFIG_KEY_TO_FILE: tgt_fn = CONFIG_KEY_TO_FILE[key][0] tgt_perms = CONFIG_KEY_TO_FILE[key][1] util.write_file(tgt_fn, val, tgt_perms) for (priv, pub) in PRIV_TO_PUB.items(): if pub in cfg['ssh_keys'] or priv not in cfg['ssh_keys']: continue pair = (CONFIG_KEY_TO_FILE[priv][0], CONFIG_KEY_TO_FILE[pub][0]) cmd = ['sh', '-xc', KEY_GEN_TPL % pair] try: # TODO(harlowja): Is this guard needed? with util.SeLinuxGuard("/etc/ssh", recursive=True): subp.subp(cmd, capture=False) log.debug("Generated a key for %s from %s", pair[0], pair[1]) except Exception: util.logexc(log, "Failed generated a key for %s from %s", pair[0], pair[1]) else: # if not, generate them genkeys = util.get_cfg_option_list(cfg, 'ssh_genkeytypes', GENERATE_KEY_NAMES) lang_c = os.environ.copy() lang_c['LANG'] = 'C' for keytype in genkeys: keyfile = KEY_FILE_TPL % (keytype) if os.path.exists(keyfile): continue util.ensure_dir(os.path.dirname(keyfile)) cmd = ['ssh-keygen', '-t', keytype, '-N', '', '-f', keyfile] # TODO(harlowja): Is this guard needed? with util.SeLinuxGuard("/etc/ssh", recursive=True): try: out, err = subp.subp(cmd, capture=True, env=lang_c) sys.stdout.write(util.decode_binary(out)) except subp.ProcessExecutionError as e: err = util.decode_binary(e.stderr).lower() if (e.exit_code == 1 and err.lower().startswith("unknown key")): log.debug("ssh-keygen: unknown key type '%s'", keytype) else: util.logexc( log, "Failed generating key type %s to " "file %s", keytype, keyfile) if "ssh_publish_hostkeys" in cfg: host_key_blacklist = util.get_cfg_option_list( cfg["ssh_publish_hostkeys"], "blacklist", HOST_KEY_PUBLISH_BLACKLIST) publish_hostkeys = util.get_cfg_option_bool( cfg["ssh_publish_hostkeys"], "enabled", PUBLISH_HOST_KEYS) else: host_key_blacklist = HOST_KEY_PUBLISH_BLACKLIST publish_hostkeys = PUBLISH_HOST_KEYS if publish_hostkeys: hostkeys = get_public_host_keys(blacklist=host_key_blacklist) try: cloud.datasource.publish_host_keys(hostkeys) except Exception: util.logexc(log, "Publishing host keys failed!") try: (users, _groups) = ug_util.normalize_users_groups(cfg, cloud.distro) (user, _user_config) = ug_util.extract_default(users) disable_root = util.get_cfg_option_bool(cfg, "disable_root", True) disable_root_opts = util.get_cfg_option_str(cfg, "disable_root_opts", ssh_util.DISABLE_USER_OPTS) keys = [] if util.get_cfg_option_bool(cfg, 'allow_public_ssh_keys', True): keys = cloud.get_public_ssh_keys() or [] else: log.debug('Skipping import of publish SSH keys per ' 'config setting: allow_public_ssh_keys=False') if "ssh_authorized_keys" in cfg: cfgkeys = cfg["ssh_authorized_keys"] keys.extend(cfgkeys) apply_credentials(keys, user, disable_root, disable_root_opts) except Exception: util.logexc(log, "Applying SSH credentials failed!")
def handle(_name, cfg, cloud, log, _args): # remove the static keys from the pristine image if cfg.get("ssh_deletekeys", True): key_pth = os.path.join("/etc/ssh/", "ssh_host_*key*") for f in glob.glob(key_pth): try: util.del_file(f) except: util.logexc(log, "Failed deleting key file %s", f) if "ssh_keys" in cfg: # if there are keys in cloud-config, use them for (key, val) in cfg["ssh_keys"].items(): if key in KEY_2_FILE: tgt_fn = KEY_2_FILE[key][0] tgt_perms = KEY_2_FILE[key][1] util.write_file(tgt_fn, val, tgt_perms) for (priv, pub) in PRIV_2_PUB.items(): if pub in cfg['ssh_keys'] or priv not in cfg['ssh_keys']: continue pair = (KEY_2_FILE[priv][0], KEY_2_FILE[pub][0]) cmd = ['sh', '-xc', KEY_GEN_TPL % pair] try: # TODO(harlowja): Is this guard needed? with util.SeLinuxGuard("/etc/ssh", recursive=True): util.subp(cmd, capture=False) log.debug("Generated a key for %s from %s", pair[0], pair[1]) except: util.logexc(log, "Failed generated a key for %s from %s", pair[0], pair[1]) else: # if not, generate them genkeys = util.get_cfg_option_list(cfg, 'ssh_genkeytypes', GENERATE_KEY_NAMES) for keytype in genkeys: keyfile = KEY_FILE_TPL % (keytype) util.ensure_dir(os.path.dirname(keyfile)) if not os.path.exists(keyfile): cmd = ['ssh-keygen', '-t', keytype, '-N', '', '-f', keyfile] try: # TODO(harlowja): Is this guard needed? with util.SeLinuxGuard("/etc/ssh", recursive=True): util.subp(cmd, capture=False) except: util.logexc(log, "Failed generating key type %s to " "file %s", keytype, keyfile) try: (users, _groups) = ds.normalize_users_groups(cfg, cloud.distro) (user, _user_config) = ds.extract_default(users) disable_root = util.get_cfg_option_bool(cfg, "disable_root", True) disable_root_opts = util.get_cfg_option_str(cfg, "disable_root_opts", DISABLE_ROOT_OPTS) keys = cloud.get_public_ssh_keys() or [] if "ssh_authorized_keys" in cfg: cfgkeys = cfg["ssh_authorized_keys"] keys.extend(cfgkeys) apply_credentials(keys, user, disable_root, disable_root_opts) except: util.logexc(log, "Applying ssh credentials failed!")
def check_create_path(username, filename, strictmodes): user_pwent = users_ssh_info(username)[1] root_pwent = users_ssh_info("root")[1] try: # check the directories first directories = filename.split("/")[1:-1] # scan in order, from root to file name parent_folder = "" # this is to comply also with unit tests, and # strange home directories home_folder = os.path.dirname(user_pwent.pw_dir) for directory in directories: parent_folder += "/" + directory # security check, disallow symlinks in the AuthorizedKeysFile path. if os.path.islink(parent_folder): LOG.debug("Invalid directory. Symlink exists in path: %s", parent_folder) return False if os.path.isfile(parent_folder): LOG.debug("Invalid directory. File exists in path: %s", parent_folder) return False if (home_folder.startswith(parent_folder) or parent_folder == user_pwent.pw_dir): continue if not os.path.exists(parent_folder): # directory does not exist, and permission so far are good: # create the directory, and make it accessible by everyone # but owned by root, as it might be used by many users. with util.SeLinuxGuard(parent_folder): mode = 0o755 uid = root_pwent.pw_uid gid = root_pwent.pw_gid if parent_folder.startswith(user_pwent.pw_dir): mode = 0o700 uid = user_pwent.pw_uid gid = user_pwent.pw_gid os.makedirs(parent_folder, mode=mode, exist_ok=True) util.chownbyid(parent_folder, uid, gid) permissions = check_permissions(username, parent_folder, filename, False, strictmodes) if not permissions: return False if os.path.islink(filename) or os.path.isdir(filename): LOG.debug("%s is not a file!", filename) return False # check the file if not os.path.exists(filename): # if file does not exist: we need to create it, since the # folders at this point exist and have right permissions util.write_file(filename, '', mode=0o600, ensure_dir_exists=True) util.chownbyid(filename, user_pwent.pw_uid, user_pwent.pw_gid) permissions = check_permissions(username, filename, filename, True, strictmodes) if not permissions: return False except (IOError, OSError) as e: util.logexc(LOG, str(e)) return False return True
def handle(_name, cfg, cloud, log, _args): # remove the static keys from the pristine image if cfg.get("ssh_deletekeys", True): key_pth = os.path.join("/etc/ssh/", "ssh_host_*key*") for f in glob.glob(key_pth): try: util.del_file(f) except Exception: util.logexc(log, "Failed deleting key file %s", f) if "ssh_keys" in cfg: # if there are keys and/or certificates in cloud-config, use them for (key, val) in cfg["ssh_keys"].items(): # skip entry if unrecognized if key not in CONFIG_KEY_TO_FILE: continue tgt_fn = CONFIG_KEY_TO_FILE[key][0] tgt_perms = CONFIG_KEY_TO_FILE[key][1] util.write_file(tgt_fn, val, tgt_perms) # set server to present the most recently identified certificate if "_certificate" in key: cert_config = {"HostCertificate": tgt_fn} ssh_util.update_ssh_config(cert_config) for (priv, pub) in PRIV_TO_PUB.items(): if pub in cfg["ssh_keys"] or priv not in cfg["ssh_keys"]: continue pair = (CONFIG_KEY_TO_FILE[priv][0], CONFIG_KEY_TO_FILE[pub][0]) cmd = ["sh", "-xc", KEY_GEN_TPL % pair] try: # TODO(harlowja): Is this guard needed? with util.SeLinuxGuard("/etc/ssh", recursive=True): subp.subp(cmd, capture=False) log.debug("Generated a key for %s from %s", pair[0], pair[1]) except Exception: util.logexc( log, "Failed generated a key for %s from %s", pair[0], pair[1], ) else: # if not, generate them genkeys = util.get_cfg_option_list(cfg, "ssh_genkeytypes", GENERATE_KEY_NAMES) lang_c = os.environ.copy() lang_c["LANG"] = "C" for keytype in genkeys: keyfile = KEY_FILE_TPL % (keytype) if os.path.exists(keyfile): continue util.ensure_dir(os.path.dirname(keyfile)) cmd = ["ssh-keygen", "-t", keytype, "-N", "", "-f", keyfile] # TODO(harlowja): Is this guard needed? with util.SeLinuxGuard("/etc/ssh", recursive=True): try: out, err = subp.subp(cmd, capture=True, env=lang_c) if not util.get_cfg_option_bool(cfg, "ssh_quiet_keygen", False): sys.stdout.write(util.decode_binary(out)) gid = util.get_group_id("ssh_keys") if gid != -1: # perform same "sanitize permissions" as sshd-keygen os.chown(keyfile, -1, gid) os.chmod(keyfile, 0o640) os.chmod(keyfile + ".pub", 0o644) except subp.ProcessExecutionError as e: err = util.decode_binary(e.stderr).lower() if e.exit_code == 1 and err.lower().startswith( "unknown key"): log.debug("ssh-keygen: unknown key type '%s'", keytype) else: util.logexc( log, "Failed generating key type %s to file %s", keytype, keyfile, ) if "ssh_publish_hostkeys" in cfg: host_key_blacklist = util.get_cfg_option_list( cfg["ssh_publish_hostkeys"], "blacklist", HOST_KEY_PUBLISH_BLACKLIST, ) publish_hostkeys = util.get_cfg_option_bool( cfg["ssh_publish_hostkeys"], "enabled", PUBLISH_HOST_KEYS) else: host_key_blacklist = HOST_KEY_PUBLISH_BLACKLIST publish_hostkeys = PUBLISH_HOST_KEYS if publish_hostkeys: hostkeys = get_public_host_keys(blacklist=host_key_blacklist) try: cloud.datasource.publish_host_keys(hostkeys) except Exception: util.logexc(log, "Publishing host keys failed!") try: (users, _groups) = ug_util.normalize_users_groups(cfg, cloud.distro) (user, _user_config) = ug_util.extract_default(users) disable_root = util.get_cfg_option_bool(cfg, "disable_root", True) disable_root_opts = util.get_cfg_option_str(cfg, "disable_root_opts", ssh_util.DISABLE_USER_OPTS) keys = [] if util.get_cfg_option_bool(cfg, "allow_public_ssh_keys", True): keys = cloud.get_public_ssh_keys() or [] else: log.debug("Skipping import of publish SSH keys per " "config setting: allow_public_ssh_keys=False") if "ssh_authorized_keys" in cfg: cfgkeys = cfg["ssh_authorized_keys"] keys.extend(cfgkeys) apply_credentials(keys, user, disable_root, disable_root_opts) except Exception: util.logexc(log, "Applying SSH credentials failed!")
def handle(_name, cfg, cloud, log, _args): meta = cloud.datasource.metadata if 'mrdb' in meta: log.debug("MRDB configuration doesn't need to handle the ssh keys") return itool = iToolKit(iparm=0, iret=0, ids=1, irow=0) itool.add(iCmd('rtvjoba', 'RTVPRDD VRMLVL(?)')) # xmlservice itool.call(itransport) # output rtvjoba = itool.dict_out('rtvjoba') sys_version = "V7R2M0" if 'error' in rtvjoba: log.debug(rtvjoba['error']) else: log.debug(rtvjoba['success']) log.debug("VRMLVL is: %s", rtvjoba['VRMLVL']) sys_version = rtvjoba['VRMLVL'] if sys_version >= V_V7R2M0: ssh_path = KET_DIR_S else: ssh_path = KEY_DIR_J # remove the static keys from the pristine image if cfg.get("ssh_deletekeys", True): key_pth = os.path.join(ssh_path, "ssh_host_*key*") for f in glob.glob(key_pth): try: util.del_file(f) except: util.logexc(log, "Failed deleting key file %s", f) LOG.debug("cfg is " + str(cfg)) if "ssh_keys" in cfg: # if there are keys in cloud-config, use them for (key, val) in cfg["ssh_keys"].items(): if key in KEY_2_FILE: tgt_fn = ssh_path + KEY_2_FILE[key][0] tgt_perms = KEY_2_FILE[key][1] LOG.debug("inserting " + str(val) + " into " + str(tgt_fn)) util.write_file(tgt_fn, val, tgt_perms) for (priv, pub) in PRIV_2_PUB.items(): if pub in cfg['ssh_keys'] or not priv in cfg['ssh_keys']: continue pair = (ssh_path + KEY_2_FILE[priv][0], ssh_path + KEY_2_FILE[pub][0]) cmd = ['sh', '-xc', KEY_GEN_TPL % pair] try: # TODO(harlowja): Is this guard needed? with util.SeLinuxGuard(ssh_path, recursive=True): util.subp(cmd, capture=False) log.debug("Generated a key for %s from %s", pair[0], pair[1]) except: util.logexc(log, "Failed generated a key for %s from %s", pair[0], pair[1]) else: # if not, generate them genkeys = util.get_cfg_option_list(cfg, 'ssh_genkeytypes', GENERATE_KEY_NAMES) key_file_p = ssh_path + KEY_FILE_TPL for keytype in genkeys: keyfile = key_file_p % (keytype) util.ensure_dir(os.path.dirname(keyfile)) if not os.path.exists(keyfile): cmd = ['ssh-keygen', '-t', keytype, '-N', '', '-f', keyfile] try: # TODO(harlowja): Is this guard needed? with util.SeLinuxGuard(ssh_path, recursive=True): util.subp(cmd, capture=False) except: util.logexc(log, "Failed generating key type %s to " "file %s", keytype, keyfile) try: (users, _groups) = ds.normalize_users_groups(cfg, cloud.distro) (user, _user_config) = ds.extract_default(users) keys = cloud.get_public_ssh_keys() or [] if "ssh_authorized_keys" in cfg: cfgkeys = cfg["ssh_authorized_keys"] keys.extend(cfgkeys) apply_credentials(keys, user) except: util.logexc(log, "Applying ssh credentials failed!")