org.apache.ambari.server.security.CertificateManager.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.ambari.server.security.CertificateManager.java

Source

/**
 * 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.ambari.server.security;

import com.google.inject.Inject;
import com.google.inject.Singleton;
import org.apache.ambari.server.configuration.Configuration;
import org.apache.ambari.server.utils.ShellCommandUtil;
import org.apache.commons.io.FileUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

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;
import java.util.Map;

/**
 * Ambari security.
 * Manages server and agent certificates
 */
@Singleton
public class CertificateManager {

    @Inject
    Configuration configs;

    private static final Log LOG = LogFactory.getLog(CertificateManager.class);

    private static final String GEN_SRVR_KEY = "openssl genrsa -des3 " + "-passout pass:{0} -out {1}"
            + File.separator + "{2} 4096 ";
    private static final String GEN_SRVR_REQ = "openssl req -passin pass:{0} " + "-new -key {1}" + File.separator
            + "{2} -out {1}" + File.separator + "{5} -batch";
    private static final String SIGN_SRVR_CRT = "openssl ca -create_serial " + "-out {1}" + File.separator
            + "{3} -days 365 -keyfile {1}" + File.separator + "{2} -key {0} -selfsign "
            + "-extensions jdk7_ca -config {1}" + File.separator + "ca.config -batch " + "-infiles {1}"
            + File.separator + "{5}";
    private static final String EXPRT_KSTR = "openssl pkcs12 -export" + " -in {1}" + File.separator
            + "{3} -inkey {1}" + File.separator + "{2} -certfile {1}" + File.separator + "{3} -out {1}"
            + File.separator + "{4} " + "-password pass:{0} -passin pass:{0} \n";
    private static final String REVOKE_AGENT_CRT = "openssl ca " + "-config {0}" + File.separator
            + "ca.config -keyfile {0}" + File.separator + "{4} -revoke {0}" + File.separator + "{2} -batch "
            + "-passin pass:{3} -cert {0}" + File.separator + "{5}";
    private static final String SIGN_AGENT_CRT = "openssl ca -config " + "{0}" + File.separator
            + "ca.config -in {0}" + File.separator + "{1} -out {0}" + File.separator
            + "{2} -batch -passin pass:{3} " + "-keyfile {0}" + File.separator + "{4} -cert {0}" + File.separator
            + "{5}";

    /**
    * Verify that root certificate exists, generate it otherwise.
    */
    public void initRootCert() {
        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() {

        Map<String, String> configsMap = configs.getConfigsMap();
        String srvrKstrDir = configsMap.get(Configuration.SRVR_KSTR_DIR_KEY);
        String srvrCrtName = configsMap.get(Configuration.SRVR_CRT_NAME_KEY);
        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();
                ShellCommandUtil.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");

        Map<String, String> configsMap = configs.getConfigsMap();
        String srvrKstrDir = configsMap.get(Configuration.SRVR_KSTR_DIR_KEY);
        String srvrCrtName = configsMap.get(Configuration.SRVR_CRT_NAME_KEY);
        String srvrCsrName = configsMap.get(Configuration.SRVR_CSR_NAME_KEY);
        ;
        String srvrKeyName = configsMap.get(Configuration.SRVR_KEY_NAME_KEY);
        String kstrName = configsMap.get(Configuration.KSTR_NAME_KEY);
        String srvrCrtPass = configsMap.get(Configuration.SRVR_CRT_PASS_KEY);

        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() {
        Map<String, String> configsMap = configs.getConfigsMap();
        File certFile = new File(configsMap.get(Configuration.SRVR_KSTR_DIR_KEY) + File.separator
                + configsMap.get(Configuration.SRVR_CRT_NAME_KEY));
        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 = configs.getConfigsMap().get(Configuration.PASSPHRASE_KEY).trim();

        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;
        }

        Map<String, String> configsMap = configs.getConfigsMap();
        String srvrKstrDir = configsMap.get(Configuration.SRVR_KSTR_DIR_KEY);
        String srvrCrtPass = configsMap.get(Configuration.SRVR_CRT_PASS_KEY);
        String srvrCrtName = configsMap.get(Configuration.SRVR_CRT_NAME_KEY);
        String srvrKeyName = configsMap.get(Configuration.SRVR_KEY_NAME_KEY);
        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(ShellCommandUtil.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(ShellCommandUtil.hideOpenSslPassword(command));

        int commandExitCode = runCommand(command); // ssl command execution
        if (commandExitCode != 0) {
            response.setResult(SignCertResponse.ERROR_STATUS);
            response.setMessage(ShellCommandUtil.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;
    }
}