Java tutorial
/** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.slider.server.services.security; import com.google.inject.Singleton; import org.apache.commons.io.FileUtils; import org.apache.slider.common.SliderKeys; import org.apache.slider.core.conf.MapOperations; import org.apache.slider.core.exceptions.SliderException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.BufferedReader; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.nio.charset.Charset; import java.text.MessageFormat; @Singleton public class CertificateManager { private static final Logger LOG = LoggerFactory.getLogger(CertificateManager.class); private static final String GEN_SRVR_KEY = "openssl genrsa -des3 " + "-passout pass:{0} -out {1}/{2} 4096 "; private static final String GEN_SRVR_REQ = "openssl req -passin pass:{0} " + "-new -key {1}/{2} -out {1}/{5} -batch"; private static final String SIGN_SRVR_CRT = "openssl ca -create_serial " + "-out {1}/{3} -days 365 -keyfile {1}/{2} -key {0} -selfsign " + "-extensions jdk7_ca -config {1}/ca.config -batch " + "-infiles {1}/{5}"; private static final String EXPRT_KSTR = "openssl pkcs12 -export" + " -in {1}/{3} -inkey {1}/{2} -certfile {1}/{3} -out {1}/{4} " + "-password pass:{0} -passin pass:{0} \n"; private static final String REVOKE_AGENT_CRT = "openssl ca " + "-config {0}/ca.config -keyfile {0}/{4} -revoke {0}/{2} -batch " + "-passin pass:{3} -cert {0}/{5}"; private static final String SIGN_AGENT_CRT = "openssl ca -config " + "{0}/ca.config -in {0}/{1} -out {0}/{2} -batch -passin pass:{3} " + "-keyfile {0}/{4} -cert {0}/{5}"; private static final String GEN_AGENT_KEY = "openssl req -new -newkey " + "rsa:1024 -nodes -keyout {0}/{2}.key -subj /OU={1}/CN={2} -out {0}/{2}.csr"; private String passphrase; /** * Verify that root certificate exists, generate it otherwise. */ public void initialize(MapOperations compOperations) { SecurityUtils.initializeSecurityParameters(compOperations); LOG.info("Initialization of root certificate"); boolean certExists = isCertExists(); LOG.info("Certificate exists:" + certExists); if (!certExists) { generateServerCertificate(); } } /** * Checks root certificate state. * @return "true" if certificate exists */ private boolean isCertExists() { String srvrKstrDir = SecurityUtils.getSecurityDir(); String srvrCrtName = SliderKeys.CRT_FILE_NAME; File certFile = new File(srvrKstrDir + File.separator + srvrCrtName); LOG.debug("srvrKstrDir = " + srvrKstrDir); LOG.debug("srvrCrtName = " + srvrCrtName); LOG.debug("certFile = " + certFile.getAbsolutePath()); return certFile.exists(); } public void setPassphrase(String passphrase) { this.passphrase = passphrase; } class StreamConsumer extends Thread { InputStream is; boolean logOutput; StreamConsumer(InputStream is, boolean logOutput) { this.is = is; this.logOutput = logOutput; } StreamConsumer(InputStream is) { this(is, false); } public void run() { try { InputStreamReader isr = new InputStreamReader(is, Charset.forName("UTF8")); BufferedReader br = new BufferedReader(isr); String line; while ((line = br.readLine()) != null) if (logOutput) { LOG.info(line); } } catch (IOException e) { LOG.error("Error during processing of process stream", e); } } } /** * Runs os command * * @return command execution exit code */ private int runCommand(String command) throws SliderException { int exitCode = -1; String line = null; Process process = null; BufferedReader br = null; try { process = Runtime.getRuntime().exec(command); StreamConsumer outputConsumer = new StreamConsumer(process.getInputStream(), true); StreamConsumer errorConsumer = new StreamConsumer(process.getErrorStream()); outputConsumer.start(); errorConsumer.start(); try { process.waitFor(); SecurityUtils.logOpenSslExitCode(command, process.exitValue()); exitCode = process.exitValue(); if (exitCode != 0) { throw new SliderException(exitCode, "Error running command %s", command); } } catch (InterruptedException e) { e.printStackTrace(); } } catch (IOException e) { e.printStackTrace(); } finally { if (br != null) { try { br.close(); } catch (IOException ioe) { ioe.printStackTrace(); } } } return exitCode;//some exception occurred } public synchronized void generateAgentCertificate(String agentHostname, String containerId) { LOG.info("Generation of agent certificate for {}", agentHostname); String srvrKstrDir = SecurityUtils.getSecurityDir(); Object[] scriptArgs = { srvrKstrDir, agentHostname, containerId }; try { String command = MessageFormat.format(GEN_AGENT_KEY, scriptArgs); runCommand(command); signAgentCertificate(containerId); } catch (SliderException e) { LOG.error("Error generating the agent certificate", e); } } private void generateServerCertificate() { LOG.info("Generation of server certificate"); String srvrKstrDir = SecurityUtils.getSecurityDir(); String srvrCrtName = SliderKeys.CRT_FILE_NAME; String srvrCsrName = SliderKeys.CSR_FILE_NAME; String srvrKeyName = SliderKeys.KEY_FILE_NAME; String kstrName = SliderKeys.KEYSTORE_FILE_NAME; String srvrCrtPass = SecurityUtils.getKeystorePass(); Object[] scriptArgs = { srvrCrtPass, srvrKstrDir, srvrKeyName, srvrCrtName, kstrName, srvrCsrName }; try { String command = MessageFormat.format(GEN_SRVR_KEY, scriptArgs); runCommand(command); command = MessageFormat.format(GEN_SRVR_REQ, scriptArgs); runCommand(command); command = MessageFormat.format(SIGN_SRVR_CRT, scriptArgs); runCommand(command); command = MessageFormat.format(EXPRT_KSTR, scriptArgs); runCommand(command); } catch (SliderException e) { LOG.error("Error generating the server certificate", e); } } /** * Returns server certificate content * @return string with server certificate content */ public String getServerCert() { File certFile = getServerCertficateFilePath(); String srvrCrtContent = null; try { srvrCrtContent = FileUtils.readFileToString(certFile); } catch (IOException e) { LOG.error(e.getMessage()); } return srvrCrtContent; } public static File getServerCertficateFilePath() { return new File(SecurityUtils.getSecurityDir() + File.separator + SliderKeys.CRT_FILE_NAME); } public static File getAgentCertficateFilePath(String containerId) { return new File(SecurityUtils.getSecurityDir() + File.separator + containerId + ".crt"); } public static File getAgentKeyFilePath(String containerId) { return new File(SecurityUtils.getSecurityDir() + File.separator + containerId + ".key"); } /** * Signs agent certificate * Adds agent certificate to server keystore * @return string with agent signed certificate content */ public synchronized SignCertResponse signAgentCrt(String agentHostname, String agentCrtReqContent, String passphraseAgent) { SignCertResponse response = new SignCertResponse(); LOG.info("Signing of agent certificate"); LOG.info("Verifying passphrase"); if (!this.passphrase.equals(passphraseAgent.trim())) { LOG.warn("Incorrect passphrase from the agent"); response.setResult(SignCertResponse.ERROR_STATUS); response.setMessage("Incorrect passphrase from the agent"); return response; } String srvrKstrDir = SecurityUtils.getSecurityDir(); String srvrCrtPass = SecurityUtils.getKeystorePass(); String srvrCrtName = SliderKeys.CRT_FILE_NAME; String srvrKeyName = SliderKeys.KEY_FILE_NAME; String agentCrtReqName = agentHostname + ".csr"; String agentCrtName = agentHostname + ".crt"; Object[] scriptArgs = { srvrKstrDir, agentCrtReqName, agentCrtName, srvrCrtPass, srvrKeyName, srvrCrtName }; //Revoke previous agent certificate if exists File agentCrtFile = new File(srvrKstrDir + File.separator + agentCrtName); String command = null; if (agentCrtFile.exists()) { LOG.info("Revoking of " + agentHostname + " certificate."); command = MessageFormat.format(REVOKE_AGENT_CRT, scriptArgs); try { runCommand(command); } catch (SliderException e) { int commandExitCode = e.getExitCode(); response.setResult(SignCertResponse.ERROR_STATUS); response.setMessage(SecurityUtils.getOpenSslCommandResult(command, commandExitCode)); return response; } } File agentCrtReqFile = new File(srvrKstrDir + File.separator + agentCrtReqName); try { FileUtils.writeStringToFile(agentCrtReqFile, agentCrtReqContent); } catch (IOException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } command = MessageFormat.format(SIGN_AGENT_CRT, scriptArgs); LOG.debug(SecurityUtils.hideOpenSslPassword(command)); try { runCommand(command); } catch (SliderException e) { int commandExitCode = e.getExitCode(); response.setResult(SignCertResponse.ERROR_STATUS); response.setMessage(SecurityUtils.getOpenSslCommandResult(command, commandExitCode)); return response; } String agentCrtContent = ""; try { agentCrtContent = FileUtils.readFileToString(agentCrtFile); } catch (IOException e) { e.printStackTrace(); LOG.error("Error reading signed agent certificate"); response.setResult(SignCertResponse.ERROR_STATUS); response.setMessage("Error reading signed agent certificate"); return response; } response.setResult(SignCertResponse.OK_STATUS); response.setSignedCa(agentCrtContent); //LOG.info(ShellCommandUtil.getOpenSslCommandResult(command, commandExitCode)); return response; } private String signAgentCertificate(String containerId) throws SliderException { String srvrKstrDir = SecurityUtils.getSecurityDir(); String srvrCrtPass = SecurityUtils.getKeystorePass(); String srvrCrtName = SliderKeys.CRT_FILE_NAME; String srvrKeyName = SliderKeys.KEY_FILE_NAME; String agentCrtReqName = containerId + ".csr"; String agentCrtName = containerId + ".crt"; Object[] scriptArgs = { srvrKstrDir, agentCrtReqName, agentCrtName, srvrCrtPass, srvrKeyName, srvrCrtName }; //Revoke previous agent certificate if exists File agentCrtFile = new File(srvrKstrDir + File.separator + agentCrtName); String command; if (agentCrtFile.exists()) { LOG.info("Revoking of " + containerId + " certificate."); command = MessageFormat.format(REVOKE_AGENT_CRT, scriptArgs); runCommand(command); } command = MessageFormat.format(SIGN_AGENT_CRT, scriptArgs); LOG.debug(SecurityUtils.hideOpenSslPassword(command)); runCommand(command); return agentCrtName; } }