package org.ovirt.engine.core.utils.hostinstall; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.text.SimpleDateFormat; import java.util.Calendar; import org.ovirt.engine.core.common.config.Config; import org.ovirt.engine.core.common.config.ConfigValues; import org.ovirt.engine.core.compat.LogCompat; import org.ovirt.engine.core.compat.LogFactoryCompat; import org.ovirt.engine.core.utils.FileUtil; public class OpenSslCAWrapper implements ICAWrapper { public final boolean SignCertificateRequest(String requestFileName, int days, String signedCertificateFileName) { log.debug("Entered SignCertificateRequest"); boolean returnValue = true; String signRequestBatch = Config.resolveSignScriptPath(); if (FileUtil.fileExists(signRequestBatch)) { Integer signatureTimeout = Config.<Integer> GetValue(ConfigValues.SignCertTimeoutInSeconds); String[] command_array = createCommandArray(signatureTimeout, signRequestBatch, requestFileName, days, signedCertificateFileName); returnValue = runCommandArray(command_array, signatureTimeout); } else { log.error(String.format("Sign certificate request file '%s' not found", signRequestBatch)); returnValue = false; } log.debug("End of SignCertificateRequest"); return returnValue; } /** * Runs the SignReq.sh script * @param command_array * @param signatureTimeout * @return whether or not the certificate signing was successful */ private boolean runCommandArray(String[] command_array, int signatureTimeout) { boolean returnValue = true; String outputString = null; String errorString = null; BufferedReader stdOutput = null; BufferedReader stdError = null; try { log.debug("Running Sign Certificate request script"); Process process = getRuntime().exec(command_array); stdOutput = new BufferedReader(new InputStreamReader(process.getInputStream())); stdError = new BufferedReader(new InputStreamReader(process.getErrorStream())); int exitCode = 0; boolean completed = false; for (int x = 0; x < signatureTimeout; x++) { try { Thread.sleep(1000); exitCode = process.exitValue(); completed = true; break; } catch (IllegalThreadStateException e) { // keep going } catch (InterruptedException ie) { // keep going } } outputString += readAllLines(stdOutput); errorString += readAllLines(stdError); if (!completed) { process.destroy(); returnValue = false; log.error("Sign Certificate request script killed due to timeout"); logOutputAndErrors(outputString, errorString); } else if (exitCode != 0) { returnValue = false; log.error("Sign Certificate request failed with exit code " + exitCode); logOutputAndErrors(outputString, errorString); } else { log.debug("Successfully completed certificate signing script"); } } catch (IOException e) { log.error("Exception signing the certificate", e); logOutputAndErrors(outputString, errorString); returnValue = false; } finally { // Close the BufferedReaders try { if (stdOutput != null) { stdOutput.close(); } if (stdError != null) { stdError.close(); } } catch (IOException ex) { log.error("Unable to close BufferedReader"); } } return returnValue; } /** * Returns a formatted String from the content of the given bufferedReader * @param bufferedReader */ private String readAllLines(BufferedReader bufferedReader) { String tempString; StringBuilder returnString = new StringBuilder(); try { while ((tempString = bufferedReader.readLine()) != null) { returnString.append(tempString).append('\n'); } } catch (IOException e) { log.error("IOException while trying to read from buffer", e); } return returnString.toString(); } /** * Prepares a String array in order to run the SignReq.sh script * @param signatureTimeout * @param signRequestBatch * the script name * @param requestFileName * @param days * @param signedCertificateFileName * @return the command_array ready to run */ private String[] createCommandArray(Integer signatureTimeout, String signRequestBatch, String requestFileName, int days, String signedCertificateFileName) { log.debug("Building command array for Sign Certificate request script"); String baseDirectoryPath = Config.resolveCABasePath(); String keystorePass = Config.<String> GetValue(ConfigValues.keystorePass); String lockfileName = Config.<String> GetValue(ConfigValues.SignLockFile); Calendar today = Calendar.getInstance(); today.add(Calendar.DATE, -1); SimpleDateFormat format = new SimpleDateFormat("yyMMddHHmmssZ"); String yesterday = format.format(today.getTime()); String[] command_array = { signRequestBatch, requestFileName, signedCertificateFileName, "" + days, baseDirectoryPath, yesterday, keystorePass, lockfileName, "" + (signatureTimeout / 2) }; log.debug("Finished building command array for Sign Certificate request script"); return command_array; } /** * Logs the given output to DEBUG, and the given errors to ERROR * @param output * The formatted output from the script * @param errors * The formatted errors from the script */ private void logOutputAndErrors(String output, String errors) { if (errors != null && errors.length() != 0) { log.error("Sign Certificate request script errors:\n" + errors); } if (output != null && output.length() != 0) { log.debug("Sign Certificate request script output:\n" + output); } } /** * This method is meant to enable testing, since Runtime cannot be mocked statically */ protected Runtime getRuntime() { return Runtime.getRuntime(); } private static LogCompat log = LogFactoryCompat.getLog(OpenSslCAWrapper.class); }