diff --git a/lib/backend.py b/lib/backend.py index 215be6c6b439aabdb910935f01a684c07baef49c..5df65a574eec213366e86a354b0becb48949d292 100644 --- a/lib/backend.py +++ b/lib/backend.py @@ -88,28 +88,24 @@ def AddNode(dsa, dsapub, rsa, rsapub, sshkey, sshpub): - adds the ssh public key to the users' authorized_keys file """ - user_dir = utils.GetHomeDir(constants.GANETI_RUNAS) - if not user_dir: - logger.Error("Cannot find home of run-as user %s" % constants.GANETI_RUNAS) - return False - - sshd_keys = [("ssh_host_rsa_key", rsa, 0600), - ("ssh_host_rsa_key.pub", rsapub, 0644), - ("ssh_host_dsa_key", dsa, 0600), - ("ssh_host_dsa_key.pub", dsapub, 0644)] + sshd_keys = [(constants.SSH_HOST_RSA_PRIV, rsa, 0600), + (constants.SSH_HOST_RSA_PUB, rsapub, 0644), + (constants.SSH_HOST_DSA_PRIV, dsa, 0600), + (constants.SSH_HOST_DSA_PUB, dsapub, 0644)] for name, content, mode in sshd_keys: - utils.WriteFile(os.path.join(constants.SSH_CONFIG_DIR, name), - data=content, mode=mode) - - user_ssh_dir = os.path.join(user_dir, ".ssh") + utils.WriteFile(name, data=content, mode=mode) - if not os.path.isdir(user_ssh_dir): - os.mkdir(user_ssh_dir) + try: + priv_key, pub_key, auth_keys = ssh.GetUserFiles(constants.GANETI_RUNAS, + mkdir=True) + except errors.OpExecError, err: + logger.Error("Error while processing user ssh files: %s" % err) + return False - for name, content in [("id_dsa", sshkey), ("id_dsa.pub", sshpub)]: - utils.WriteFile(os.path.join(user_ssh_dir, name), data=content, mode=0600) + for name, content in [(priv_key, sshkey), (pub_key, sshpub)]: + utils.WriteFile(name, data=content, mode=0600) - utils.AddAuthorizedKey(os.path.join(user_ssh_dir, "authorized_keys"), sshpub) + utils.AddAuthorizedKey(auth_keys, sshpub) utils.RunCmd([constants.SSH_INITD_SCRIPT, "restart"]) @@ -126,27 +122,21 @@ def LeaveCluster(): if os.path.isfile(full_name) and not os.path.islink(full_name): utils.RemoveFile(full_name) - user_dir = utils.GetHomeDir(constants.GANETI_RUNAS) - if not user_dir: - logger.Error("Cannot find home of run-as user %s" % constants.GANETI_RUNAS) - return - - user_ssh_dir = os.path.join(user_dir, ".ssh") - if not os.path.isdir(user_ssh_dir): - logger.Error("User's ssh dir '%s' does not exist?!" % user_ssh_dir) + try: + priv_key, pub_key, auth_keys = ssh.GetUserFiles(constants.GANETI_RUNAS) + except errors.OpExecError, err: + logger.Error("Error while processing ssh files: %s" % err) return - f = open(os.path.join(user_ssh_dir, "id_dsa.pub"), 'r') + f = open(pub_key, 'r') try: - utils.RemoveAuthorizedKey(os.path.join(user_ssh_dir, "authorized_keys"), - f.read(8192)) + utils.RemoveAuthorizedKey(auth_keys, f.read(8192)) finally: f.close() - - utils.RemoveFile(os.path.join(user_ssh_dir, "id_dsa")) - utils.RemoveFile(os.path.join(user_ssh_dir, "id_dsa.pub")) + utils.RemoveFile(priv_key) + utils.RemoveFile(pub_key) def GetNodeInfo(vgname): diff --git a/lib/cmdlib.py b/lib/cmdlib.py index 46c5c6e1c055c921fedc90ac416f041f1aaa7020..ea563459123ff54db3f2a7413975ea5a6add63bd 100644 --- a/lib/cmdlib.py +++ b/lib/cmdlib.py @@ -476,24 +476,23 @@ def _InitSSHSetup(node): node: the name of this host as a fqdn """ - if os.path.exists('/root/.ssh/id_dsa'): - utils.CreateBackup('/root/.ssh/id_dsa') - if os.path.exists('/root/.ssh/id_dsa.pub'): - utils.CreateBackup('/root/.ssh/id_dsa.pub') + priv_key, pub_key, auth_keys = ssh.GetUserFiles(constants.GANETI_RUNAS) - utils.RemoveFile('/root/.ssh/id_dsa') - utils.RemoveFile('/root/.ssh/id_dsa.pub') + for name in priv_key, pub_key: + if os.path.exists(name): + utils.CreateBackup(name) + utils.RemoveFile(name) result = utils.RunCmd(["ssh-keygen", "-t", "dsa", - "-f", "/root/.ssh/id_dsa", + "-f", priv_key, "-q", "-N", ""]) if result.failed: raise errors.OpExecError("Could not generate ssh keypair, error %s" % result.output) - f = open('/root/.ssh/id_dsa.pub', 'r') + f = open(pub_key, 'r') try: - utils.AddAuthorizedKey('/root/.ssh/authorized_keys', f.read(8192)) + utils.AddAuthorizedKey(auth_keys, f.read(8192)) finally: f.close() @@ -627,7 +626,7 @@ class LUInitCluster(LogicalUnit): rpc.call_node_start_master(hostname.name) # set up ssh config and /etc/hosts - f = open('/etc/ssh/ssh_host_rsa_key.pub', 'r') + f = open(constants.SSH_HOST_RSA_PUB, 'r') try: sshline = f.read() finally: @@ -676,8 +675,9 @@ class LUDestroyCluster(NoHooksLU): """Destroys the cluster. """ - utils.CreateBackup('/root/.ssh/id_dsa') - utils.CreateBackup('/root/.ssh/id_dsa.pub') + priv_key, pub_key, _ = ssh.GetUserFiles(constants.GANETI_RUNAS) + utils.CreateBackup(priv_key) + utils.CreateBackup(pub_key) rpc.call_node_leave_cluster(self.sstore.GetMasterNode()) @@ -1508,10 +1508,11 @@ class LUAddNode(LogicalUnit): # setup ssh on node logger.Info("copy ssh key to node %s" % node) + priv_key, pub_key, _ = ssh.GetUserFiles(constants.GANETI_RUNAS) keyarray = [] - keyfiles = ["/etc/ssh/ssh_host_dsa_key", "/etc/ssh/ssh_host_dsa_key.pub", - "/etc/ssh/ssh_host_rsa_key", "/etc/ssh/ssh_host_rsa_key.pub", - "/root/.ssh/id_dsa", "/root/.ssh/id_dsa.pub"] + keyfiles = [constants.SSH_HOST_DSA_PRIV, constants.SSH_HOST_DSA_PUB, + constants.SSH_HOST_RSA_PRIV, constants.SSH_HOST_RSA_PUB, + priv_key, pub_key] for i in keyfiles: f = open(i, 'r') diff --git a/lib/constants.py b/lib/constants.py index 60dbb183b106fa988ecfbf74ea82f9a5180d9a41..e7b33d5733f34e60eb7aecaf29e97122b47da860 100644 --- a/lib/constants.py +++ b/lib/constants.py @@ -110,6 +110,10 @@ LOCALHOST_IP_ADDRESS="127.0.0.1" TCP_PING_TIMEOUT = 10 GANETI_RUNAS = "root" -# external utilities +# ssh constants SSH_INITD_SCRIPT = _autoconf.SSH_INITD_SCRIPT -SSH_CONFIG_DIR = "/etc/ssh" +SSH_CONFIG_DIR = "/etc/ssh/" +SSH_HOST_DSA_PRIV = SSH_CONFIG_DIR + "ssh_host_dsa_key" +SSH_HOST_DSA_PUB = SSH_HOST_DSA_PRIV + ".pub" +SSH_HOST_RSA_PRIV = SSH_CONFIG_DIR + "ssh_host_rsa_key" +SSH_HOST_RSA_PUB = SSH_HOST_RSA_PRIV + ".pub" diff --git a/lib/ssh.py b/lib/ssh.py index d82319d3209e5b1dd0c944f75054534c1959ed2b..2caab463ebc32aaf45326218ad04837c99969b45 100644 --- a/lib/ssh.py +++ b/lib/ssh.py @@ -55,6 +55,41 @@ ASK_KEY_OPTS = [ ] +def GetUserFiles(user, mkdir=False): + """Return the paths of a user's ssh files. + + The function will return a triplet (priv_key_path, pub_key_path, + auth_key_path) that are used for ssh authentication. Currently, the + keys used are DSA keys, so this function will return: + (~user/.ssh/id_dsa, ~user/.ssh/id_dsa.pub, + ~user/.ssh/authorized_keys). + + If the optional parameter mkdir is True, the ssh directory will be + created if it doesn't exist. + + Regardless of the mkdir parameters, the script will raise an error + if ~user/.ssh is not a directory. + + """ + user_dir = utils.GetHomeDir(user) + if not user_dir: + raise errors.OpExecError("Cannot resolve home of user %s" % user) + + ssh_dir = os.path.join(user_dir, ".ssh") + if not os.path.lexists(ssh_dir): + if mkdir: + try: + os.mkdir(ssh_dir, 0700) + except EnvironmentError, err: + raise errors.OpExecError("Can't create .ssh dir for user %s: %s" % + (user, str(err))) + elif not os.path.isdir(ssh_dir): + raise errors.OpExecError("path ~%s/.ssh is not a directory" % user) + + return [os.path.join(ssh_dir, base) + for base in ["id_dsa", "id_dsa.pub", "authorized_keys"]] + + def BuildSSHCmd(hostname, user, command, batch=True, ask_key=False): """Build an ssh string to execute a command on a remote node.