org.apache.slider.server.services.security.SecurityUtils.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.slider.server.services.security.SecurityUtils.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.slider.server.services.security;

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.RandomStringUtils;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.fs.RawLocalFileSystem;
import org.apache.hadoop.fs.permission.FsAction;
import org.apache.hadoop.fs.permission.FsPermission;
import org.apache.slider.common.SliderKeys;
import org.apache.slider.common.SliderXmlConfKeys;
import org.apache.slider.core.conf.MapOperations;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.IOException;
//import java.nio.file.Files;
//import java.nio.file.Path;
//import java.nio.file.Paths;
//import java.nio.file.attribute.PosixFilePermission;
//import java.nio.file.attribute.PosixFilePermissions;

/**
 *
 */
public class SecurityUtils {
    private static final Logger LOG = LoggerFactory.getLogger(SecurityUtils.class);

    private static String CA_CONFIG_CONTENTS = "[ ca ]\n" + "default_ca             = CA_CLIENT\n"
            + "[ CA_CLIENT ]\n" + "dir\t\t       = ${SEC_DIR}/db\n" + "certs                  = $dir/certs\n"
            + "new_certs_dir          = $dir/newcerts\n" + "\n" + "database               = $dir/index.txt\n"
            + "serial                 = $dir/serial\n" + "default_days           = 365    \n" + "\n"
            + "default_crl_days       = 7  \n" + "default_md             = md5 \n" + "\n"
            + "policy                 = policy_anything \n" + "\n" + "[ policy_anything ]\n"
            + "countryName            = optional\n" + "stateOrProvinceName    = optional \n"
            + "localityName           = optional\n" + "organizationName       = optional\n"
            + "organizationalUnitName = optional\n" + "commonName             = optional   \n"
            + "emailAddress           = optional       \n" + "\n" + "[ jdk7_ca ]\n"
            + "subjectKeyIdentifier = hash\n" + "authorityKeyIdentifier = keyid:always,issuer:always\n"
            + "basicConstraints = CA:true";

    private static final String PASS_TOKEN = "pass:";
    private static String keystorePass;
    private static String securityDir;

    public static void logOpenSslExitCode(String command, int exitCode) {
        if (exitCode == 0) {
            LOG.info(getOpenSslCommandResult(command, exitCode));
        } else {
            LOG.warn(getOpenSslCommandResult(command, exitCode));
        }

    }

    public static String hideOpenSslPassword(String command) {
        int start = command.indexOf(PASS_TOKEN) + PASS_TOKEN.length();
        CharSequence cs = command.subSequence(start, command.indexOf(" ", start));
        return command.replace(cs, "****");
    }

    public static String getOpenSslCommandResult(String command, int exitCode) {
        return new StringBuilder().append("Command ").append(hideOpenSslPassword(command))
                .append(" was finished with exit code: ").append(exitCode).append(" - ")
                .append(getOpenSslExitCodeDescription(exitCode)).toString();
    }

    private static String getOpenSslExitCodeDescription(int exitCode) {
        switch (exitCode) {
        case 0: {
            return "the operation was completed successfully.";
        }
        case 1: {
            return "an error occurred parsing the command options.";
        }
        case 2: {
            return "one of the input files could not be read.";
        }
        case 3: {
            return "an error occurred creating the PKCS#7 file or when reading the MIME message.";
        }
        case 4: {
            return "an error occurred decrypting or verifying the message.";
        }
        case 5: {
            return "the message was verified correctly but an error occurred writing out the signers certificates.";
        }
        default:
            return "unsupported code";
        }
    }

    public static void writeCaConfigFile(String path) throws IOException {
        String contents = CA_CONFIG_CONTENTS.replace("${SEC_DIR}", path);
        FileUtils.writeStringToFile(new File(path, "ca.config"), contents);
    }

    public static String getKeystorePass() {
        return keystorePass;
    }

    public static String getSecurityDir() {
        return securityDir;
    }

    public static void initializeSecurityParameters(MapOperations configMap) {
        initializeSecurityParameters(configMap, false);
    }

    public static void initializeSecurityParameters(MapOperations configMap, boolean persistPassword) {
        String keyStoreLocation = configMap.getOption(SliderXmlConfKeys.KEY_KEYSTORE_LOCATION,
                getDefaultKeystoreLocation());
        File secDirFile = new File(keyStoreLocation).getParentFile();
        if (!secDirFile.exists()) {
            // create entire required directory structure
            File dbDir = new File(secDirFile, "db");
            File newCertsDir = new File(dbDir, "newcerts");
            newCertsDir.mkdirs();
            try {
                RawLocalFileSystem fileSystem = new RawLocalFileSystem();
                FsPermission permissions = new FsPermission(FsAction.ALL, FsAction.NONE, FsAction.NONE);
                fileSystem.setPermission(new Path(dbDir.getAbsolutePath()), permissions);
                fileSystem.setPermission(new Path(dbDir.getAbsolutePath()), permissions);
                fileSystem.setPermission(new Path(newCertsDir.getAbsolutePath()), permissions);
                File indexFile = new File(dbDir, "index.txt");
                indexFile.createNewFile();

                SecurityUtils.writeCaConfigFile(secDirFile.getAbsolutePath().replace('\\', '/'));

            } catch (IOException e) {
                LOG.error("Unable to create SSL configuration directories/files", e);
            }
            // need to create the password
        }
        keystorePass = getKeystorePassword(secDirFile, persistPassword);
        securityDir = secDirFile.getAbsolutePath();
    }

    private static String getKeystorePassword(File secDirFile, boolean persistPassword) {
        File passFile = new File(secDirFile, SliderKeys.CRT_PASS_FILE_NAME);
        String password = null;
        if (!passFile.exists()) {
            LOG.info("Generating keystore password");
            password = RandomStringUtils.randomAlphanumeric(Integer.valueOf(SliderKeys.PASS_LEN));
            if (persistPassword) {
                try {
                    FileUtils.writeStringToFile(passFile, password);
                    passFile.setWritable(true);
                    passFile.setReadable(true);
                } catch (IOException e) {
                    e.printStackTrace();
                    throw new RuntimeException("Error creating certificate password file");
                }
            }
        } else {
            LOG.info("Reading password from existing file");
            try {
                password = FileUtils.readFileToString(passFile);
                password = password.replaceAll("\\p{Cntrl}", "");
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        return password;
    }

    private static String getDefaultKeystoreLocation() {
        File workDir = null;
        try {
            workDir = new File(
                    FileUtils.getTempDirectory().getAbsolutePath() + "/sec" + System.currentTimeMillis());
            if (!workDir.mkdirs()) {
                throw new IOException("Unable to create temporary security directory");
            }
        } catch (IOException e) {
            LOG.warn("Unable to create security directory");
            return null;
        }

        return new StringBuilder().append(workDir.getAbsolutePath()).append(File.separator)
                .append(SliderKeys.SECURITY_DIR).append(File.separator).append(SliderKeys.KEYSTORE_FILE_NAME)
                .toString();
    }

}