blob: 3771208c147886a91b3064cb07f25effe8f6d7b8 [file] [log] [blame]
/**
* 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.commons.lang.RandomStringUtils;
import org.apache.hadoop.yarn.api.ApplicationConstants;
import org.apache.slider.common.SliderKeys;
import org.apache.slider.core.conf.MapOperations;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
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}"; /**
* Verify that root certificate exists, generate it otherwise.
*/
public void initRootCert(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();
}
/**
* Runs os command
*
* @return command execution exit code
*/
private int runCommand(String command) {
String line = null;
Process process = null;
BufferedReader br= null;
try {
process = Runtime.getRuntime().exec(command);
br = new BufferedReader(new InputStreamReader(
process.getInputStream(), Charset.forName("UTF8")));
while ((line = br.readLine()) != null) {
LOG.info(line);
}
try {
process.waitFor();
SecurityUtils.logOpenSslExitCode(command, process.exitValue());
return process.exitValue(); //command is executed
} catch (InterruptedException e) {
e.printStackTrace();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (br != null) {
try {
br.close();
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
}
return -1;//some exception occurred
}
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};
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);
}
/**
* Returns server certificate content
* @return string with server certificate content
*/
public String getServerCert() {
File certFile = new File(SecurityUtils.getSecurityDir() +
File.separator + SliderKeys.CRT_FILE_NAME);
String srvrCrtContent = null;
try {
srvrCrtContent = FileUtils.readFileToString(certFile);
} catch (IOException e) {
LOG.error(e.getMessage());
}
return srvrCrtContent;
}
/**
* 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");
String passphraseSrvr = SliderKeys.PASSPHRASE;
if (!passphraseSrvr.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);
if (agentCrtFile.exists()) {
LOG.info("Revoking of " + agentHostname + " certificate.");
String command = MessageFormat.format(REVOKE_AGENT_CRT, scriptArgs);
int commandExitCode = runCommand(command);
if (commandExitCode != 0) {
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();
}
String command = MessageFormat.format(SIGN_AGENT_CRT, scriptArgs);
LOG.debug(SecurityUtils.hideOpenSslPassword(command));
int commandExitCode = runCommand(command); // ssl command execution
if (commandExitCode != 0) {
response.setResult(SignCertResponse.ERROR_STATUS);
response.setMessage(
SecurityUtils.getOpenSslCommandResult(command, commandExitCode));
//LOG.warn(ShellCommandUtil.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;
}
}