Java tutorial
/** * VMware Continuent Tungsten Replicator * Copyright (C) 2015 VMware, Inc. All rights reserved. * * Licensed 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. * * Initial developer(s): Ludovic Launer * Contributor(s): */ package com.continuent.tungsten.common.security; import java.security.UnrecoverableKeyException; import java.text.MessageFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.NoSuchElementException; import java.util.Scanner; import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.CommandLineParser; import org.apache.commons.cli.GnuParser; import org.apache.commons.cli.HelpFormatter; import org.apache.commons.cli.Option; import org.apache.commons.cli.OptionBuilder; import org.apache.commons.cli.OptionGroup; import org.apache.commons.cli.Options; import org.apache.commons.cli.ParseException; import org.apache.log4j.Logger; import com.continuent.tungsten.common.security.SecurityConf.KEYSTORE_TYPE; /** * Application to manage passwords and users * * @author <a href="mailto:ludovic.launer@continuent.com">Ludovic Launer</a> * @version 1.0 */ public class KeystoreManagerCtrl { private static Logger logger = Logger.getLogger(KeystoreManagerCtrl.class); private static KeystoreManagerCtrl keystoreManager = null; private Options helpOptions = new Options(); private Options options = new Options(); // --- Options overriding elements in security.properties --- private String keystoreLocation = null; private String keyAlias = null; private KEYSTORE_TYPE keyType = null; private String keystorePassword = null; private String keyPassword = null; // -- Define constants for command line arguments --- private static final String HELP = "help"; private static final String _HELP = "h"; private static final String _CHECK = "c"; private static final String CHECK = "check"; private static final String KEYSTORE_LOCATION = "keystore.location"; private static final String _KEYSTORE_LOCATION = "ks"; private static final String KEYSTORE_PASSWORD = "keystore.password"; private static final String _KEYSTORE_PASSWORD = "ksp"; private static final String KEY_ALIAS = "key.alias"; private static final String _KEY_ALIAS = "ka"; private static final String KEY_TYPE = "key.type"; private static final String _KEY_TYPE = "kt"; private static final String KEY_PASSWORD = "key.password"; private static final String _KEY_PASSWORD = "kp"; private static Option check; // --- Exit codes --- public enum EXIT_CODE { EXIT_OK(0), EXIT_ERROR(1); final int value; private EXIT_CODE(int value) { this.value = value; } } /** * Setup command line options */ @SuppressWarnings("static-access") private void setupCommandLine() { // --- Options on the command line --- Option help = OptionBuilder.withLongOpt(HELP).withDescription("Displays this message").create(_HELP); // Mutually excluding options OptionGroup optionGroup = new OptionGroup(); check = OptionBuilder.withLongOpt(CHECK).hasArgs(0).withDescription("Checks key password inside a keystore") .create(_CHECK); optionGroup.addOption(check); optionGroup.setRequired(true); // At least 1 command required // --- Options replacing parameters from security.properties --- Option keystoreLocation = OptionBuilder.withLongOpt(KEYSTORE_LOCATION).withArgName("filename").hasArg() .withDescription("Location of the keystore file").isRequired().create(_KEYSTORE_LOCATION); Option keyAlias = OptionBuilder.withLongOpt(KEY_ALIAS).withArgName("key alias").hasArg().isRequired() .withDescription("Alias for the key").create(_KEY_ALIAS); Option keyType = OptionBuilder.withLongOpt(KEY_TYPE).withArgName("key type").hasArg().isRequired() .withDescription(MessageFormat.format("Type of key: {0}", KEYSTORE_TYPE.getListValues("|"))) .create(_KEY_TYPE); Option keystorePassword = OptionBuilder.withLongOpt(KEYSTORE_PASSWORD).withArgName("password").hasArg() .withDescription("Password for the keystore file").create(_KEYSTORE_PASSWORD); Option keyPassword = OptionBuilder.withLongOpt(KEY_PASSWORD).withArgName("key password").hasArg() .withDescription("Password for the key").create(_KEY_PASSWORD); // --- Add options to the list --- // --- Help this.helpOptions.addOption(help); // --- Program command line options this.options.addOptionGroup(optionGroup); this.options.addOption(help); this.options.addOption(keystoreLocation); this.options.addOption(keyAlias); this.options.addOption(keyType); this.options.addOption(keystorePassword); this.options.addOption(keyPassword); } /** * Creates a new <code>PasswordManager</code> object */ public KeystoreManagerCtrl() { this.setupCommandLine(); } /** * Password Manager entry point * * @param argv * @throws Exception */ public static void main(String argv[]) throws Exception { keystoreManager = new KeystoreManagerCtrl(); // --- Options --- CommandLine line = null; try { CommandLineParser parser = new GnuParser(); // --- Parse the command line arguments --- // --- Help line = parser.parse(keystoreManager.helpOptions, argv, true); if (line.hasOption(_HELP)) { DisplayHelpAndExit(EXIT_CODE.EXIT_OK); } // --- Program command line options line = parser.parse(keystoreManager.options, argv); // --- Compulsory arguments : Get options --- if (line.hasOption(_KEYSTORE_LOCATION)) keystoreManager.keystoreLocation = line.getOptionValue(_KEYSTORE_LOCATION); if (line.hasOption(_KEY_ALIAS)) keystoreManager.keyAlias = line.getOptionValue(_KEY_ALIAS); if (line.hasOption(_KEY_TYPE)) { String keyType = line.getOptionValue(_KEY_TYPE); // This will throw an exception if the type is not recognised KEYSTORE_TYPE certificateTYpe = KEYSTORE_TYPE.fromString(keyType); keystoreManager.keyType = certificateTYpe; } if (line.hasOption(_KEYSTORE_PASSWORD)) keystoreManager.keystorePassword = line.getOptionValue(_KEYSTORE_PASSWORD); if (line.hasOption(_KEY_PASSWORD)) keystoreManager.keyPassword = line.getOptionValue(_KEY_PASSWORD); } catch (ParseException exp) { logger.error(exp.getMessage()); DisplayHelpAndExit(EXIT_CODE.EXIT_ERROR); } catch (Exception e) { // Workaround for Junit test if (e.toString().contains("CheckExitCalled")) { throw e; } else // Normal behaviour { logger.error(e.getMessage()); Exit(EXIT_CODE.EXIT_ERROR); } } // --- Perform commands --- // ######### Check password ########## if (line.hasOption(_CHECK)) { try { if (keystoreManager.keystorePassword == null || keystoreManager.keyPassword == null) { // --- Get passwords from stdin if not given on command line List<String> listPrompts = Arrays.asList("Keystore password:", MessageFormat.format("Password for key {0}:", keystoreManager.keyAlias)); List<String> listUserInput = keystoreManager.getUserInputFromStdin(listPrompts); if (listUserInput.size() == listPrompts.size()) { keystoreManager.keystorePassword = listUserInput.get(0); keystoreManager.keyPassword = listUserInput.get(1); } else { throw new NoSuchElementException(); } } try { // --- Check that all keys in keystore use the keystore // password logger.info(MessageFormat.format("Using keystore:{0}", keystoreManager.keystoreLocation)); SecurityHelper.checkKeyStorePasswords(keystoreManager.keystoreLocation, keystoreManager.keyType, keystoreManager.keystorePassword, keystoreManager.keyAlias, keystoreManager.keyPassword); logger.info(MessageFormat.format("OK : Identical password for Keystore and key={0}", keystoreManager.keyAlias)); } catch (UnrecoverableKeyException uke) { logger.error(MessageFormat.format("At least 1 key has a wrong password.{0}", uke.getMessage())); Exit(EXIT_CODE.EXIT_ERROR); } catch (Exception e) { logger.error(MessageFormat.format("{0}", e.getMessage())); Exit(EXIT_CODE.EXIT_ERROR); } } catch (NoSuchElementException nse) { logger.error(nse.getMessage()); Exit(EXIT_CODE.EXIT_ERROR); } catch (Exception e) { logger.error(MessageFormat.format("Error while running the program: {0}", e.getMessage())); Exit(EXIT_CODE.EXIT_ERROR); } } Exit(EXIT_CODE.EXIT_OK); } /** * Reads user input from stdin * * @param listPrompts list of prompts to display, asking for user input * @return a list containing user inputs */ private List<String> getUserInputFromStdin(List<String> listPrompts) { List<String> listUserInput = new ArrayList<String>(); Scanner console = new Scanner(System.in); Scanner lineTokenizer = null; for (String prompt : listPrompts) { System.out.println(prompt); try { lineTokenizer = new Scanner(console.nextLine()); } catch (NoSuchElementException nse) { console.close(); throw new NoSuchElementException(MessageFormat.format("Missing user input= {0}", prompt)); } if (lineTokenizer.hasNext()) { String userInput = lineTokenizer.next(); listUserInput.add(userInput); } } console.close(); return listUserInput; } /** * Display the program help and exits */ private static void DisplayHelpAndExit(EXIT_CODE exitCode) { HelpFormatter formatter = new HelpFormatter(); formatter.setWidth(120); formatter.printHelp("tkeystoremanager", keystoreManager.options); Exit(exitCode); } private static void Exit(EXIT_CODE exitCode) { System.exit(exitCode.value); } }