From cc0ed77feed5e5adc7cfdf9e8babe58d696e148e Mon Sep 17 00:00:00 2001 From: Chiradeep Vittal Date: Fri, 28 Jan 2011 12:24:00 -0800 Subject: [PATCH] bug 8199: always update the keypairs on disk to account for multiple management servers --- scripts/vm/systemvm/injectkeys.sh | 17 ++-- scripts/vm/systemvm/injectkeys2.sh | 65 ++++++++++++++++ .../cloud/server/ConfigurationServerImpl.java | 78 +++++++++++++++---- 3 files changed, 135 insertions(+), 25 deletions(-) create mode 100755 scripts/vm/systemvm/injectkeys2.sh diff --git a/scripts/vm/systemvm/injectkeys.sh b/scripts/vm/systemvm/injectkeys.sh index 26b6b4bd41e..e562b11b36c 100755 --- a/scripts/vm/systemvm/injectkeys.sh +++ b/scripts/vm/systemvm/injectkeys.sh @@ -5,7 +5,7 @@ #set -x -TMP=/tmp +TMP=${HOME}/tmp SYSTEMVM_PATCH_DIR=../../../vms/ MOUNTPATH=/mnt/cloud/systemvm TMPDIR=${TMP}/cloud/systemvm @@ -17,23 +17,23 @@ inject_into_iso() { local backup=${isofile}.bak local tmpiso=${TMP}/$1 [ ! -f $isofile ] && echo "$(basename $0): Could not find systemvm iso patch file $isofile" && return 1 - mount -o loop $isofile $MOUNTPATH + sudo mount -o loop $isofile $MOUNTPATH [ $? -ne 0 ] && echo "$(basename $0): Failed to mount original iso $isofile" && return 1 diff -q $MOUNTPATH/authorized_keys $newpubkey &> /dev/null && return 0 - cp -b $isofile $backup + sudo cp -b $isofile $backup [ $? -ne 0 ] && echo "$(basename $0): Failed to backup original iso $isofile" && return 1 rm -rf $TMPDIR mkdir -p $TMPDIR [ ! -d $TMPDIR ] && echo "$(basename $0): Could not find/create temporary dir $TMPDIR" && return 1 - cp -fr $MOUNTPATH/* $TMPDIR/ + sudo cp -fr $MOUNTPATH/* $TMPDIR/ [ $? -ne 0 ] && echo "$(basename $0): Failed to copy from original iso $isofile" && return 1 - cp $newpubkey $TMPDIR/authorized_keys + sudo cp $newpubkey $TMPDIR/authorized_keys [ $? -ne 0 ] && echo "$(basename $0): Failed to copy key $newpubkey from original iso to new iso " && return 1 mkisofs -quiet -r -o $tmpiso $TMPDIR [ $? -ne 0 ] && echo "$(basename $0): Failed to create new iso $tmpiso from $TMPDIR" && return 1 - umount $MOUNTPATH + sudo umount $MOUNTPATH [ $? -ne 0 ] && echo "$(basename $0): Failed to unmount old iso from $MOUNTPATH" && return 1 - cp -f $tmpiso $isofile + sudo cp -f $tmpiso $isofile [ $? -ne 0 ] && echo "$(basename $0): Failed to overwrite old iso $isofile with $tmpiso" && return 1 rm -rf $TMPDIR } @@ -41,7 +41,7 @@ inject_into_iso() { copy_priv_key() { local newprivkey=$1 diff -q $newprivkey $(dirname $0)/id_rsa.cloud && return 0 - cp -fb $newprivkey $(dirname $0)/id_rsa.cloud && chmod 0600 $(dirname $0)/id_rsa.cloud + sudo cp -fb $newprivkey $(dirname $0)/id_rsa.cloud return $? } @@ -52,7 +52,6 @@ newpubkey=$1 newprivkey=$2 [ ! -f $newpubkey ] && echo "$(basename $0): Could not open $newpubkey" && exit 3 [ ! -f $newprivkey ] && echo "$(basename $0): Could not open $newprivkey" && exit 3 -[ $EUID -ne 0 ] && echo "$(basename $0): You have to be root to run this script" && exit 3 command -v mkisofs > /dev/null || (echo "$(basename $0): mkisofs not found, please install or ensure PATH is accurate" ; exit 4) diff --git a/scripts/vm/systemvm/injectkeys2.sh b/scripts/vm/systemvm/injectkeys2.sh new file mode 100755 index 00000000000..cab8e9b5c77 --- /dev/null +++ b/scripts/vm/systemvm/injectkeys2.sh @@ -0,0 +1,65 @@ +#!/bin/bash +# Copies keys that enable SSH communication with system vms +# $1 = new public key +# $2 = new private key + +set -x + +TMP=${HOME}/tmp +SYSTEMVM_PATCH_DIR=../../../vms/ +MOUNTPATH=/mnt/cloud/systemvm +TMPDIR=${TMP}/cloud/systemvm + + +inject_into_iso() { + local isofile=${SYSTEMVM_PATCH_DIR}/$1 + local newpubkey=$2 + local backup=${isofile}.bak + local tmpiso=${TMP}/$1 + [ ! -f $isofile ] && echo "$(basename $0): Could not find systemvm iso patch file $isofile" && return 1 + sudo mount -o loop $isofile $MOUNTPATH + [ $? -ne 0 ] && echo "$(basename $0): Failed to mount original iso $isofile" && return 1 + diff -q $MOUNTPATH/authorized_keys $newpubkey &> /dev/null && return 0 + sudo cp -b $isofile $backup + [ $? -ne 0 ] && echo "$(basename $0): Failed to backup original iso $isofile" && return 1 + rm -rf $TMPDIR + mkdir -p $TMPDIR + [ ! -d $TMPDIR ] && echo "$(basename $0): Could not find/create temporary dir $TMPDIR" && return 1 + sudo cp -fr $MOUNTPATH/* $TMPDIR/ + [ $? -ne 0 ] && echo "$(basename $0): Failed to copy from original iso $isofile" && return 1 + sudo cp $newpubkey $TMPDIR/authorized_keys + [ $? -ne 0 ] && echo "$(basename $0): Failed to copy key $newpubkey from original iso to new iso " && return 1 + mkisofs -quiet -r -o $tmpiso $TMPDIR + [ $? -ne 0 ] && echo "$(basename $0): Failed to create new iso $tmpiso from $TMPDIR" && return 1 + sudo umount $MOUNTPATH + [ $? -ne 0 ] && echo "$(basename $0): Failed to unmount old iso from $MOUNTPATH" && return 1 + #cp -f $tmpiso $isofile + #[ $? -ne 0 ] && echo "$(basename $0): Failed to overwrite old iso $isofile with $tmpiso" && return 1 + rm -rf $TMPDIR +} + +copy_priv_key() { + local newprivkey=$1 + diff -q $newprivkey $(dirname $0)/id_rsa.cloud && return 0 + sudo cp -fb $newprivkey $(dirname $0)/id_rsa.cloud && sudo chmod 0600 $(dirname $0)/id_rsa.cloud + return $? +} + +mkdir -p $MOUNTPATH + +[ $# -ne 2 ] && echo "Usage: $(basename $0) " && exit 3 +newpubkey=$1 +newprivkey=$2 +[ ! -f $newpubkey ] && echo "$(basename $0): Could not open $newpubkey" && exit 3 +[ ! -f $newprivkey ] && echo "$(basename $0): Could not open $newprivkey" && exit 3 + +command -v mkisofs > /dev/null || (echo "$(basename $0): mkisofs not found, please install or ensure PATH is accurate" ; exit 4) + +inject_into_iso systemvm.iso $newpubkey +#inject_into_iso systemvm-premium.iso $newpubkey + +[ $? -ne 0 ] && exit 5 + +copy_priv_key $newprivkey + +exit $? diff --git a/server/src/com/cloud/server/ConfigurationServerImpl.java b/server/src/com/cloud/server/ConfigurationServerImpl.java index 3a6243b6482..23d24a1df6b 100644 --- a/server/src/com/cloud/server/ConfigurationServerImpl.java +++ b/server/src/com/cloud/server/ConfigurationServerImpl.java @@ -22,6 +22,8 @@ import java.io.DataInputStream; import java.io.EOFException; import java.io.File; import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; import java.io.IOException; import java.math.BigInteger; import java.net.NetworkInterface; @@ -30,6 +32,7 @@ import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.sql.PreparedStatement; import java.sql.SQLException; +import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Properties; @@ -393,29 +396,28 @@ public class ConfigurationServerImpl implements ConfigurationServer { s_logger.info("Processing updateKeyPairs"); } String already = _configDao.getValue("ssh.privatekey"); + String homeDir = Script.runSimpleBashScript("echo ~"); + String userid = System.getProperty("user.name"); + if (homeDir == "~") { + s_logger.error("No home directory was detected. Set the HOME environment variable to point to your user profile or home directory."); + throw new CloudRuntimeException("No home directory was detected. Set the HOME environment variable to point to your user profile or home directory."); + } + File privkeyfile = new File(homeDir + "/.ssh/id_rsa"); + File pubkeyfile = new File(homeDir + "/.ssh/id_rsa.pub"); if (already == null || already.isEmpty()) { if (s_logger.isInfoEnabled()) { s_logger.info("Need to store in the database"); } + Script.runSimpleBashScript("if [ -f ~/.ssh/id_rsa ] ; then true ; else yes '' | ssh-keygen -t rsa -q ; fi"); - String homeDir = Script.runSimpleBashScript("echo ~"); - if (homeDir == "~") { - s_logger.error("No home directory was detected. Set the HOME environment variable to point to your user profile or home directory."); - throw new RuntimeException("No home directory was detected. Set the HOME environment variable to point to your user profile or home directory."); - } - - String keygenOutput = Script.runSimpleBashScript("if [ -f ~/.ssh/id_rsa ] ; then true ; else yes '' | ssh-keygen -t rsa -q ; fi"); - - File privkeyfile = new File(homeDir + "/.ssh/id_rsa"); - File pubkeyfile = new File(homeDir + "/.ssh/id_rsa.pub"); byte[] arr1 = new byte[4094]; // configuration table column value size try { new DataInputStream(new FileInputStream(privkeyfile)).readFully(arr1); } catch (EOFException e) { } catch (Exception e) { s_logger.error("Cannot read the private key file",e); - throw new RuntimeException("Cannot read the private key file"); + throw new CloudRuntimeException("Cannot read the private key file"); } String privateKey = new String(arr1).trim(); byte[] arr2 = new byte[4094]; // configuration table column value size @@ -424,7 +426,7 @@ public class ConfigurationServerImpl implements ConfigurationServer { } catch (EOFException e) { } catch (Exception e) { s_logger.warn("Cannot read the public key file",e); - throw new RuntimeException("Cannot read the public key file"); + throw new CloudRuntimeException("Cannot read the public key file"); } String publicKey = new String(arr2).trim(); @@ -442,7 +444,7 @@ public class ConfigurationServerImpl implements ConfigurationServer { } } catch (SQLException ex) { s_logger.error("SQL of the private key failed",ex); - throw new RuntimeException("SQL of the private key failed"); + throw new CloudRuntimeException("SQL of the private key failed"); } try { @@ -453,19 +455,62 @@ public class ConfigurationServerImpl implements ConfigurationServer { } } catch (SQLException ex) { s_logger.error("SQL of the public key failed",ex); - throw new RuntimeException("SQL of the public key failed"); + throw new CloudRuntimeException("SQL of the public key failed"); } - injectSshKeyIntoSystemVmIsoPatch(pubkeyfile.getAbsolutePath()); + if (s_logger.isDebugEnabled()) { s_logger.debug("Public key inserted into systemvm iso"); } } else { s_logger.info("Keypairs already in database"); + if (userid.startsWith("cloud")) { + s_logger.info("Keypairs already in database, updating local copy"); + updateKeyPairsOnDisk(homeDir); + } + } + if (userid.startsWith("cloud")){ + s_logger.info("Going to update systemvm iso with generated keypairs if needed"); + injectSshKeysIntoSystemVmIsoPatch(pubkeyfile.getAbsolutePath(), privkeyfile.getAbsolutePath()); } } + private void writeKeyToDisk(String key, String keyPath) { - protected void injectSshKeyIntoSystemVmIsoPatch(String publicKeyPath) { + File keyfile = new File( keyPath); + if (!keyfile.exists()) { + try { + keyfile.createNewFile(); + } catch (IOException e) { + s_logger.warn("Failed to create file: " + e.toString()); + throw new CloudRuntimeException("Failed to update keypairs on disk: cannot create key file " + keyPath); + } + } + + if (keyfile.exists()) { + try { + FileOutputStream kStream = new FileOutputStream(keyfile); + kStream.write(key.getBytes()); + kStream.close(); + } catch (FileNotFoundException e) { + s_logger.warn("Failed to write key to " + keyfile.getAbsolutePath()); + throw new CloudRuntimeException("Failed to update keypairs on disk: cannot find key file " + keyPath); + } catch (IOException e) { + s_logger.warn("Failed to write key to " + keyfile.getAbsolutePath()); + throw new CloudRuntimeException("Failed to update keypairs on disk: cannot write to key file " + keyPath); + } + } + + } + + private void updateKeyPairsOnDisk(String homeDir ) { + + String pubKey = _configDao.getValue("ssh.publickey"); + String prvKey = _configDao.getValue("ssh.privatekey"); + writeKeyToDisk(homeDir + "/.ssh/id_rsa", prvKey); + writeKeyToDisk(homeDir + "/.ssh/id_rsa.pub", pubKey); + } + + protected void injectSshKeysIntoSystemVmIsoPatch(String publicKeyPath, String privKeyPath) { String injectScript = "scripts/vm/systemvm/injectkeys.sh"; String scriptPath = Script.findScript("" , injectScript); if ( scriptPath == null ) { @@ -473,6 +518,7 @@ public class ConfigurationServerImpl implements ConfigurationServer { } final Script command = new Script(scriptPath, s_logger); command.add(publicKeyPath); + command.add(privKeyPath); final String result = command.execute(); if (result != null) {