/** * 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 */ package com.continuent.tungsten.common.security; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.security.GeneralSecurityException; import java.security.KeyStore; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import java.text.MessageFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Enumeration; import java.util.HashMap; import java.util.List; import javax.xml.bind.annotation.XmlRootElement; import org.apache.log4j.Logger; import org.codehaus.jackson.JsonGenerationException; import org.codehaus.jackson.JsonParseException; import org.codehaus.jackson.annotate.JsonIgnore; import org.codehaus.jackson.map.JsonMappingException; import org.codehaus.jackson.map.ObjectMapper; import org.codehaus.jackson.map.ObjectWriter; import org.codehaus.jackson.map.SerializationConfig.Feature; import org.codehaus.jackson.map.annotate.JsonSerialize; import com.continuent.tungsten.common.config.TungstenProperties; import com.continuent.tungsten.common.config.cluster.ClusterConfiguration; import com.continuent.tungsten.common.config.cluster.ConfigurationException; import com.continuent.tungsten.common.jmx.ServerRuntimeException; import com.continuent.tungsten.common.security.SecurityConf.KEYSTORE_TYPE; import com.continuent.tungsten.common.security.SecurityHelper.TUNGSTEN_APPLICATION_NAME; import com.continuent.tungsten.common.utils.CLLogLevel; import com.continuent.tungsten.common.utils.CLUtils; /** * Information class holding Authentication and Encryption parameters Some of * the properties may be left null depending on how and when this is used * * @author <a href="mailto:ludovic.launer@continuent.com">Ludovic Launer</a> * @version 1.0 */ @XmlRootElement @JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL) public final class AuthenticationInfo implements Cloneable { private static final Logger logger = Logger .getLogger(AuthenticationInfo.class); /** Location of the file from which this was built **/ private String parentPropertiesFileLocation = null; /** Properties from the files from which this was built **/ private TungstenProperties parentProperties = null; private TUNGSTEN_APPLICATION_NAME tungstenApplicationName = null; private boolean authenticationNeeded = false; private Integer minWaitOnFailedLogin = null; // (ms) private Integer maxWaitOnFailedLogin = null; // (ms) private Integer incrementStepWaitOnFailedLogin = 1; private boolean authenticationByCertificateNeeded = false; private boolean encryptionNeeded = false; private boolean useTungstenAuthenticationRealm = true; private boolean useEncryptedPasswords = false; /** Set to true if the connector should be using SSL **/ private boolean connectorUseSSL = false; // Authentication parameters private String username = null; private String password = null; private String passwordFileLocation = null; private String accessFileLocation = null; // Encryption parameters private String keystoreLocation = null; private String keystorePassword = null; private String clientKeystoreLocation = null; private String clientKeystorePassword = null; private String truststoreLocation = null; private String truststorePassword = null; private List<String> enabledProtocols = null; private List<String> enabledCipherSuites = null; // Alias for entries in keystore // key=identifier as defined in SecurityConf value=alias for this // application private HashMap<String, String> mapKeystoreAliasesForTungstenApplication = new HashMap<String, String>(); public transient final static String SECURITY_INFO_PROPERTY = "securityInfo"; public transient final static String TUNGSTEN_AUTHENTICATION_REALM = "tungstenAutenthicationRealm"; // Possible command line parameters public transient final static String USERNAME = "-username"; public transient final static String PASSWORD = "-password"; public transient final static String KEYSTORE_LOCATION = "-keystoreLocation"; public transient final static String KEYSTORE_PASSWORD = "-keystorePassword"; public transient final static String TRUSTSTORE_LOCATION = "-truststoreLocation"; public transient final static String TRUSTSTORE_PASSWORD = "-truststorePassword"; public transient final static String SECURITY_CONFIG_FILE_LOCATION = "-securityProperties"; /** * Creates a new <code>AuthenticationInfo</code> object */ public AuthenticationInfo(String parentPropertiesFileLocation) { this.parentPropertiesFileLocation = parentPropertiesFileLocation; } public AuthenticationInfo() { this((String) null); } /** * Check Authentication information consistency * * @throws ConfigurationException */ public void checkAndCleanAuthenticationInfo() throws ServerRuntimeException, ConfigurationException { checkAndCleanAuthenticationInfo(TUNGSTEN_APPLICATION_NAME.ANY); } public void checkAndCleanAuthenticationInfo( TUNGSTEN_APPLICATION_NAME tungstenApplicationName) throws ServerRuntimeException, ConfigurationException { // --- Check security.properties location --- if (this.parentPropertiesFileLocation != null) { File f = new File(this.parentPropertiesFileLocation); // --- Find absolute path if needed if (!f.isFile()) { f = this.findAbsolutePath(f); this.parentPropertiesFileLocation = f.getAbsolutePath(); } // --- Check file is readable if (!f.isFile() || !f.canRead()) { String msg = MessageFormat.format( "Cannot find or read {0} file: {1}", SECURITY_CONFIG_FILE_LOCATION, this.parentPropertiesFileLocation); CLUtils.println(msg, CLLogLevel.detailed); throw new ServerRuntimeException(msg, new AssertionError("File must exist")); } } // --- Clean up --- if (tungstenApplicationName == TUNGSTEN_APPLICATION_NAME.CONNECTOR && !this.isConnectorUseSSL()) { // The Connector does not use SSL, delete unnecessary information. this.keystoreLocation = null; this.keystorePassword = null; this.truststoreLocation = null; this.truststorePassword = null; } // ---------------------- Check Keystore ---------------------------- String keystoreLocationProperty = (tungstenApplicationName == TUNGSTEN_APPLICATION_NAME.CONNECTOR) ? SecurityConf.CONNECTOR_SECURITY_KEYSTORE_LOCATION : SecurityConf.SECURITY_KEYSTORE_LOCATION; String keystorePasswordProperty = (tungstenApplicationName == TUNGSTEN_APPLICATION_NAME.CONNECTOR) ? SecurityConf.CONNECTOR_SECURITY_KEYSTORE_PASSWORD : SecurityConf.SECURITY_KEYSTORE_PASSWORD; if ((this.isEncryptionNeeded() && this.keystoreLocation != null) || ((tungstenApplicationName == TUNGSTEN_APPLICATION_NAME.CONNECTOR || tungstenApplicationName == TUNGSTEN_APPLICATION_NAME.REPLICATOR) && this.isConnectorUseSSL())) { // --- Check file location is specified --- if (this.keystoreLocation == null) { String msg = MessageFormat.format( "Configuration error: {0}={1} but: {2}={3}", SecurityConf.CONNECTOR_USE_SSL, this.isConnectorUseSSL(), keystoreLocationProperty, this.keystoreLocation); CLUtils.println(msg, CLLogLevel.detailed); throw new ServerRuntimeException(msg, new AssertionError("File must exist")); } File f = new File(this.keystoreLocation); // --- Find absolute path if needed if (!f.isFile()) { f = this.findAbsolutePath(f); this.keystoreLocation = f.getAbsolutePath(); } // --- Check file is readable if (!f.isFile() || !f.canRead()) { String msg = MessageFormat.format( "Cannot find or read {0} file: {1}", KEYSTORE_LOCATION, this.keystoreLocation); CLUtils.println(msg, CLLogLevel.detailed); throw new ServerRuntimeException(msg, new AssertionError("File must exist")); } // --- Check password is defined if (this.keystorePassword == null) { throw new ConfigurationException(keystorePasswordProperty); } } // --- Check that the keystore is not empty --- if ((tungstenApplicationName == TUNGSTEN_APPLICATION_NAME.REST_API && this.isEncryptionNeeded()) || (tungstenApplicationName == TUNGSTEN_APPLICATION_NAME.CONNECTOR && this.connectorUseSSL) || this.isEncryptionNeeded()) { boolean succp = false; /** * Check accessibility of both key store and keys with a given * password */ for (KEYSTORE_TYPE keystoreType : KEYSTORE_TYPE .values()) { try { SecurityHelper.checkKeyStorePasswords( this.getKeystoreLocation(), keystoreType, this.getKeystorePassword(), null, this.getKeystorePassword()); } catch (GeneralSecurityException e) { continue; } catch (IOException e) { continue; } succp = true; } if (!succp) { String message = "Can't access key store " + this.keystoreLocation + " with the given password."; logger.error(message); throw new ConfigurationException(message); } // Check keystore: should be accessible, and not empty SecurityHelper.checkAccessAndAliasesForKeystore( this.getKeystoreLocation(), this.getKeystorePassword(), true); } // --- Check that the keystore and truststore --- if (tungstenApplicationName == TUNGSTEN_APPLICATION_NAME.REST_API && this.isEncryptionNeeded()) { // Check truststore: should be accessible SecurityHelper.checkAccessAndAliasesForKeystore( this.getTruststoreLocation(), this.getTruststorePassword(), false); if (this.isAuthenticationNeeded() && this.isAuthenticationByCertificateNeeded()) { // Check client keystore: should be accessible, and not empty SecurityHelper.checkAccessAndAliasesForKeystore( this.getClientKeystoreLocation(), this.getClientKeystorePassword(), true); } } // --- Check Aliases are defined in the keystore --- if ((this.isEncryptionNeeded() && this.keystoreLocation != null) || ((tungstenApplicationName == TUNGSTEN_APPLICATION_NAME.CONNECTOR || tungstenApplicationName == TUNGSTEN_APPLICATION_NAME.REPLICATOR) && this.isConnectorUseSSL())) { FileInputStream is = null; try { // Aliases to check HashMap<String, String> mapAliases = this .getMapKeystoreAliasesForTungstenApplication(); boolean connector_alias_client_to_connector_isFound = false; boolean connector_alias_connector_to_db_isFound = false; boolean replicator_alias_master_to_slave_isFound = false; String connector_alias_client_to_connector = mapAliases.get( SecurityConf.KEYSTORE_ALIAS_CONNECTOR_CLIENT_TO_CONNECTOR); String connector_alias_connector_to_db = mapAliases.get( SecurityConf.KEYSTORE_ALIAS_CONNECTOR_CONNECTOR_TO_DB); String replicator_alias_master_to_slave = mapAliases.get( SecurityConf.KEYSTORE_ALIAS_REPLICATOR_MASTER_TO_SLAVE); // If an aliase is not defined, do not look for it...obviously connector_alias_client_to_connector_isFound = (connector_alias_client_to_connector == null) ? true : false; connector_alias_connector_to_db_isFound = (connector_alias_connector_to_db == null) ? true : false; // Load the keystore in the user's home directory // Check only if there are aliases to find if (!connector_alias_client_to_connector_isFound || !connector_alias_connector_to_db_isFound || !replicator_alias_master_to_slave_isFound) { is = new FileInputStream(this.getKeystoreLocation()); KeyStore keystore = KeyStore .getInstance(KeyStore.getDefaultType()); String password = this.getKeystorePassword(); keystore.load(is, password.toCharArray()); // List the aliases Enumeration<String> enumAliases = keystore.aliases(); while (enumAliases.hasMoreElements()) { String alias = enumAliases.nextElement(); // Does alias refer to a private key? // boolean b = keystore.isKeyEntry(alias); // Does alias refer to a trusted certificate? // b = keystore.isCertificateEntry(alias); connector_alias_client_to_connector_isFound = connector_alias_client_to_connector_isFound == true || (connector_alias_client_to_connector != null && connector_alias_client_to_connector .equals(alias)); connector_alias_connector_to_db_isFound = connector_alias_connector_to_db_isFound == true || (connector_alias_connector_to_db != null && connector_alias_connector_to_db .equals(alias)); replicator_alias_master_to_slave_isFound = replicator_alias_master_to_slave_isFound == true || (replicator_alias_master_to_slave != null && replicator_alias_master_to_slave .equals(alias)); } // --- Exception when an alias is defined but not found --- // --- Connector // Client to Connector if (tungstenApplicationName == TUNGSTEN_APPLICATION_NAME.CONNECTOR) { // Client to Connector this.buildAndThrowExceptionforMissingAlias( connector_alias_client_to_connector, connector_alias_client_to_connector_isFound, SecurityConf.KEYSTORE_ALIAS_CONNECTOR_CLIENT_TO_CONNECTOR, is); // Connector to DB this.buildAndThrowExceptionforMissingAlias( connector_alias_connector_to_db, connector_alias_connector_to_db_isFound, SecurityConf.KEYSTORE_ALIAS_CONNECTOR_CONNECTOR_TO_DB, is); } // --- Replicator if (tungstenApplicationName == TUNGSTEN_APPLICATION_NAME.REPLICATOR) { this.buildAndThrowExceptionforMissingAlias( replicator_alias_master_to_slave, replicator_alias_master_to_slave_isFound, SecurityConf.KEYSTORE_ALIAS_REPLICATOR_MASTER_TO_SLAVE, is); } } } catch (java.security.cert.CertificateException e) { this.closeInputStream(is); throw new ConfigurationException(e.getMessage()); } catch (NoSuchAlgorithmException e) { this.closeInputStream(is); throw new ConfigurationException(e.getMessage()); } catch (FileNotFoundException e) { this.closeInputStream(is); // Noting to do: this has already been checked } catch (KeyStoreException e) { this.closeInputStream(is); throw new ConfigurationException(e.getMessage()); } catch (IOException e) { this.closeInputStream(is); throw new ConfigurationException(e.getMessage()); } this.closeInputStream(is); // Close inputStream if not already done } // --- Check Truststore location --- if ((this.isEncryptionNeeded() && this.truststoreLocation != null) || (tungstenApplicationName == TUNGSTEN_APPLICATION_NAME.CONNECTOR && this.isConnectorUseSSL())) { // --- Check file location is specified --- if (this.truststoreLocation == null) { String msg = MessageFormat.format( "Configuration error: {0}={1} but: {2}={3}", SecurityConf.CONNECTOR_USE_SSL, this.isConnectorUseSSL(), SecurityConf.CONNECTOR_SECURITY_TRUSTSTORE_LOCATION, this.truststoreLocation); CLUtils.println(msg, CLLogLevel.detailed); throw new ServerRuntimeException(msg, new AssertionError("File must exist")); } File f = new File(this.truststoreLocation); // --- Find absolute path if needed if (!f.isFile()) { f = this.findAbsolutePath(f); this.truststoreLocation = f.getAbsolutePath(); } // --- Check file is readable if (!f.isFile() || !f.canRead()) { String msg = MessageFormat.format( "Cannot find or read {0} file: {1}", TRUSTSTORE_LOCATION, this.truststoreLocation); CLUtils.println(msg, CLLogLevel.detailed); throw new ServerRuntimeException(msg, new AssertionError("File must exist")); } } else if (this.isEncryptionNeeded() && this.truststoreLocation == null) { throw new ConfigurationException("truststore.location"); } // --- Check client keystore location --- // Used by the client for certificate based authentication if (this.isAuthenticationNeeded() && this.isAuthenticationByCertificateNeeded() && tungstenApplicationName == TUNGSTEN_APPLICATION_NAME.REST_API && this.clientKeystoreLocation != null) { // --- Check file location is specified --- if (this.clientKeystoreLocation == null) { String msg = MessageFormat.format( "Configuration error: {0}={1} but: {2}={3}", SecurityConf.HTTP_REST_API_SSL_USESSL, this.isEncryptionNeeded(), SecurityConf.HTTP_REST_API_CLIENT_KEYSTORE_LOCATION, this.clientKeystoreLocation); CLUtils.println(msg, CLLogLevel.detailed); throw new ServerRuntimeException(msg, new AssertionError("File must exist")); } File f = new File(this.clientKeystoreLocation); // --- Find absolute path if needed if (!f.isFile()) { f = this.findAbsolutePath(f); this.clientKeystoreLocation = f.getAbsolutePath(); } // --- Check file is readable if (!f.isFile() || !f.canRead()) { String msg = MessageFormat.format( "Cannot find or read {0} file: {1}", KEYSTORE_LOCATION, this.clientKeystoreLocation); CLUtils.println(msg, CLLogLevel.detailed); throw new ServerRuntimeException(msg, new AssertionError("File must exist")); } } else if (this.isAuthenticationNeeded() && this.isAuthenticationByCertificateNeeded() && tungstenApplicationName == TUNGSTEN_APPLICATION_NAME.REST_API && this.clientKeystoreLocation == null) { throw new ConfigurationException( SecurityConf.HTTP_REST_API_CLIENT_KEYSTORE_LOCATION); } // --- Check password for Truststore --- if (this.isEncryptionNeeded() && this.truststorePassword == null) { throw new ConfigurationException("truststore.password"); } // --- Check password file location --- if (this.isAuthenticationNeeded() && !this.isAuthenticationByCertificateNeeded() && this.passwordFileLocation != null) { File f = new File(this.passwordFileLocation); // --- Find absolute path if needed if (!f.isFile()) { f = this.findAbsolutePath(f); this.passwordFileLocation = f.getAbsolutePath(); } // --- Check file is readable if (!f.isFile() || !f.canRead()) { String msg = MessageFormat.format( "Cannot find or read {0} file: {1}", SecurityConf.SECURITY_PASSWORD_FILE_LOCATION, this.passwordFileLocation); CLUtils.println(msg, CLLogLevel.detailed); throw new ServerRuntimeException(msg, new AssertionError("File must exist")); } } // --- Check access file location --- if (this.isAuthenticationNeeded() && this.accessFileLocation != null) { File f = new File(this.accessFileLocation); // --- Find absolute path if needed if (!f.isFile()) { f = this.findAbsolutePath(f); this.accessFileLocation = f.getAbsolutePath(); } // --- Check file is readable if (!f.isFile() || !f.canRead()) { String msg = MessageFormat.format( "Cannot find or read {0} file: {1}", SecurityConf.SECURITY_ACCESS_FILE_LOCATION, this.accessFileLocation); CLUtils.println(msg, CLLogLevel.detailed); throw new ServerRuntimeException(msg, new AssertionError("File must exist")); } } } /** * TODO: buildAndThrowExceptionforMissingAlias definition. * * @param targetAlias * @param targetAliasIsFound * @param aliasDefinitionProperty * @param inputStreamToClose */ private void buildAndThrowExceptionforMissingAlias(String targetAlias, boolean targetAliasIsFound, String aliasDefinitionProperty, InputStream inputStreamToClose) { String _aliasErrorMessage = "Keystore alias is defined as {0}={1} but cannot be found in {2}"; if (targetAlias != null && targetAliasIsFound == false) { this.closeInputStream(inputStreamToClose); String aliasErrorMessage = MessageFormat.format(_aliasErrorMessage, aliasDefinitionProperty, targetAlias, this.getKeystoreLocation()); throw new ServerRuntimeException(aliasErrorMessage, new AssertionError("Alias must exist in keystore")); } } /** * Get the AuthenticationInfo as a TungstenProperties * * @return TungstenProperties */ @JsonIgnore public TungstenProperties getAsTungstenProperties() { TungstenProperties jmxProperties = new TungstenProperties(); jmxProperties.put(SECURITY_INFO_PROPERTY, this); return jmxProperties; } // /** // * Retrieve (encrypted) password from file // * // * @throws ConfigurationException // */ // public void retrievePasswordFromFile() throws ConfigurationException // { // TungstenProperties passwordProps = SecurityHelper // .loadPasswordsFromAuthenticationInfo(this); // String username = this.getUsername(); // String goodPassword = passwordProps.get(username); // this.password = goodPassword; // // if (goodPassword == null) // throw new ConfigurationException( // MessageFormat // .format("Cannot find password for username= {0} \n PasswordFile={1}", // username, this.getPasswordFileLocation())); // } /** * Returns the decrypted password * * @return String containing the (if needed) decrypted password * @throws ConfigurationException */ public String getDecryptedPassword() throws ConfigurationException { if (this.password == null) return null; String clearTextPassword = this.password; // --- Try to decrypt the password --- if (this.useEncryptedPasswords) { Encryptor encryptor = new Encryptor(this); clearTextPassword = encryptor.decrypt(this.password); } return clearTextPassword; } /** * @return the encrypted password if useEncryptedPasswords==true or the * clear text password otherwise */ public String getPassword() { return this.password; } public void setKeystore(String keyStoreLocation, String keystorePassword) { this.setKeystoreLocation(keyStoreLocation); this.setKeystorePassword(keystorePassword); } public void setTruststore(String truststoreLocation, String truststorePassword) { this.setTruststoreLocation(truststoreLocation); this.setTruststorePassword(truststorePassword); } public boolean isAuthenticationNeeded() { return authenticationNeeded; } /** * Returns the minWaitOnFailedLogin value. * * @return Returns the minWaitOnFailedLogin. */ public Integer getMinWaitOnFailedLogin() { return minWaitOnFailedLogin; } /** * Returns the maxWaitOnFailedLogin value. * * @return Returns the maxWaitOnFailedLogin. */ public Integer getMaxWaitOnFailedLogin() { return maxWaitOnFailedLogin; } /** * Sets the maxWaitOnFailedLogin value. * * @param maxWaitOnFailedLogin The maxWaitOnFailedLogin to set. */ public void setMaxWaitOnFailedLogin(Integer maxWaitOnFailedLogin) { this.maxWaitOnFailedLogin = maxWaitOnFailedLogin; } /** * Returns the incrementStepWaitOnFailedLogin value. * * @return Returns the incrementStepWaitOnFailedLogin. */ public Integer getIncrementStepWaitOnFailedLogin() { return incrementStepWaitOnFailedLogin; } /** * Sets the incrementStepWaitOnFailedLogin value. * * @param incrementStepWaitOnFailedLogin The incrementStepWaitOnFailedLogin * to set. */ public void setIncrementStepWaitOnFailedLogin( Integer incrementStepWaitOnFailedLogin) { this.incrementStepWaitOnFailedLogin = incrementStepWaitOnFailedLogin; } /** * Sets the minWaitOnFailedLogin value. * * @param minWaitOnFailedLogin The minWaitOnFailedLogin to set. */ public void setMinWaitOnFailedLogin(Integer minWaitOnFailedLogin) { this.minWaitOnFailedLogin = minWaitOnFailedLogin; } public void setAuthenticationNeeded(boolean authenticationNeeded) { this.authenticationNeeded = authenticationNeeded; } /** * Returns the authenticationByCertificateNeeded value. * * @return Returns the authenticationByCertificateNeeded. */ public boolean isAuthenticationByCertificateNeeded() { return authenticationByCertificateNeeded; } /** * Sets the authenticationByCertificateNeeded value. * * @param authenticationByCertificateNeeded The * authenticationByCertificateNeeded to set. */ public void setAuthenticationByCertificateNeeded( boolean authenticationByCertificateNeeded) { this.authenticationByCertificateNeeded = authenticationByCertificateNeeded; } public boolean isEncryptionNeeded() { return encryptionNeeded; } public void setEncryptionNeeded(boolean encryptionNeeded) { this.encryptionNeeded = encryptionNeeded; } public String getKeystoreLocation() { return keystoreLocation; } public void setKeystoreLocation(String keystoreLocation) { this.keystoreLocation = keystoreLocation; } /** * Returns the clientKeystoreLocation value. * * @return Returns the clientKeystoreLocation. */ public String getClientKeystoreLocation() { return clientKeystoreLocation; } /** * Sets the clientKeystoreLocation value. * * @param clientKeystoreLocation The clientKeystoreLocation to set. */ public void setClientKeystoreLocation(String clientKeystoreLocation) { this.clientKeystoreLocation = clientKeystoreLocation; } /** * Returns the clientKeystorePassword value. * * @return Returns the clientKeystorePassword. */ public String getClientKeystorePassword() { return clientKeystorePassword; } /** * Sets the clientKeystorePassword value. * * @param clientKeystorePassword The clientKeystorePassword to set. */ public void setClientKeystorePassword(String clientKeystorePassword) { this.clientKeystorePassword = clientKeystorePassword; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public void setPassword(String password) { this.password = password; } public String getPasswordFileLocation() { return passwordFileLocation; } public void setPasswordFileLocation(String passwordFileLocation) { this.passwordFileLocation = passwordFileLocation; } public String getAccessFileLocation() { return accessFileLocation; } public void setAccessFileLocation(String accessFileLocation) { this.accessFileLocation = accessFileLocation; } public String getKeystorePassword() { return keystorePassword; } public void setKeystorePassword(String keystorePassword) { this.keystorePassword = keystorePassword; } public String getTruststoreLocation() { return truststoreLocation; } public void setTruststoreLocation(String truststoreLocation) { this.truststoreLocation = truststoreLocation; } public String getTruststorePassword() { return truststorePassword; } public void setTruststorePassword(String truststorePassword) { this.truststorePassword = truststorePassword; } public boolean isUseTungstenAuthenticationRealm() { return useTungstenAuthenticationRealm; } public void setUseTungstenAuthenticationRealm( boolean useTungstenAuthenticationRealm) { this.useTungstenAuthenticationRealm = useTungstenAuthenticationRealm; } public boolean isUseEncryptedPasswords() { return useEncryptedPasswords; } public void setUseEncryptedPasswords(boolean useEncryptedPasswords) { this.useEncryptedPasswords = useEncryptedPasswords; } public String getParentPropertiesFileLocation() { return parentPropertiesFileLocation; } public void setParentPropertiesFileLocation( String parentPropertiesFileLocation) { this.parentPropertiesFileLocation = parentPropertiesFileLocation; } /** * Returns the connectorUseSSL value. * * @return Returns the connectorUseSSL. */ public boolean isConnectorUseSSL() { return connectorUseSSL; } /** * Sets the connectorUseSSL value. * * @param connectorUseSSL The connectorUseSSL to set. */ public void setConnectorUseSSL(boolean connectorUseSSL) { this.connectorUseSSL = connectorUseSSL; } /** * Returns the parentProperties value. * * @return Returns the parentProperties. */ public TungstenProperties getParentProperties() { return parentProperties; } /** * Sets the parentProperties value. * * @param parentProperties The parentProperties to set. */ public void setParentProperties(TungstenProperties parentProperties) { this.parentProperties = parentProperties; } /** * Returns the tungstenApplicationName value. * * @return Returns the tungstenApplicationName. */ public TUNGSTEN_APPLICATION_NAME getTungstenApplicationName() { return tungstenApplicationName; } /** * Sets the tungstenApplicationName value. * * @param tungstenApplicationName The tungstenApplicationName to set. */ public void setTungstenApplicationName( TUNGSTEN_APPLICATION_NAME tungstenApplicationName) { this.tungstenApplicationName = tungstenApplicationName; } /** * Returns the mapKeystoreAliasesForTungstenApplication value. * * @return Returns the mapKeystoreAliasesForTungstenApplication. */ public HashMap<String, String> getMapKeystoreAliasesForTungstenApplication() { return mapKeystoreAliasesForTungstenApplication; } /** * Sets the mapKeystoreAliasesForTungstenApplication value. * * @param mapKeystoreAliasesForTungstenApplication The * mapKeystoreAliasesForTungstenApplication to set. */ public void setMapKeystoreAliasesForTungstenApplication( HashMap<String, String> mapKeystoreAliasesForTungstenApplication) { this.mapKeystoreAliasesForTungstenApplication = mapKeystoreAliasesForTungstenApplication; } /** * Get the alias defined for the corresponding Tungsten application * * @param tungestenApplicationName * @return the alias defined in security.properties if it exists. null * otherwise */ public String getKeystoreAliasForConnectionType( String aliasForConnectionType) { String alias = this.mapKeystoreAliasesForTungstenApplication .get(aliasForConnectionType); return alias; } /** * Returns the enabledProtocols value. * * @return Returns the enabledProtocols. */ public List<String> getEnabledProtocols() { return enabledProtocols; } /** * Sets the enabledProtocols value. * * @param enabledProtocols The enabledProtocols to set. */ public void setEnabledProtocols(List<String> enabledProtocols) { this.enabledProtocols = enabledProtocols; } /** * Returns the enabledCipherSuites value. * * @return Returns the enabledCipherSuites. */ public List<String> getEnabledCipherSuites() { return enabledCipherSuites; } /** * Sets the enabledCipherSuites value. * * @param enabledCipherSuites The enabledCipherSuites to set. */ public void setEnabledCipherSuites(List<String> enabledCipherSuites) { this.enabledCipherSuites = enabledCipherSuites; } /** * Returns the list of ciphers that are enabled on this JVM according to the * following rule. * <ol> * <li>If the enabled cipher suites list is empty, we return the default JVM * ciphers.</li> * <li>Otherwise we take the intersection of the enabled ciphers and the * ciphers available on the JVM.</li> * </ol> */ @JsonIgnore public List<String> getJvmEnabledCipherSuites() { String[] jvmSupportedCiphers = SecurityHelper.getJvmSupportedCiphers(); if (enabledCipherSuites == null || enabledCipherSuites.size() == 0) { return Arrays.asList(jvmSupportedCiphers); } else { String[] enabledAndSupported = SecurityHelper.getJvmEnabledCiphers( enabledCipherSuites.toArray(new String[0])); return Arrays.asList(enabledAndSupported); } } /** * Try to find a file absolute path from a series of default location * * @param fileToFind the file for which to look for an absolute path * @return the file with absolute path if found. returns the same unchanged * object otherwise */ private File findAbsolutePath(File fileToFind) { File foundFile = fileToFind; try { String clusterHome = ClusterConfiguration.getClusterHome(); if (fileToFind.getPath() == fileToFind.getName()) // No absolute or // relative path // was given { // --- Try to find find in: cluster-home/conf File candidateFile = new File(clusterHome + File.separator + "conf" + File.separator + fileToFind.getName()); if (candidateFile.isFile()) { foundFile = candidateFile; logger.debug(MessageFormat.format( "File was specified with name only, and found in default location: {0}", foundFile.getAbsoluteFile())); } else throw new ConfigurationException( MessageFormat.format("File does not exist: {0}", candidateFile.getAbsolutePath())); } } catch (ConfigurationException e) { logger.debug(MessageFormat.format( "Cannot find absolute path for file: {0} \n{1}", fileToFind.getName(), e.getMessage())); return fileToFind; } return foundFile; } /** * Load values from a JSON serialized string * * @param json The JSON serialized string * @throws JsonParseException * @throws JsonMappingException * @throws IOException */ public static AuthenticationInfo loadFromJSON(String json) throws JsonParseException, JsonMappingException, IOException { ObjectMapper mapper = new ObjectMapper(); AuthenticationInfo securityInfo = mapper.readValue(json, AuthenticationInfo.class); return securityInfo; } public static AuthenticationInfo _loadFromJSON(String json) { AuthenticationInfo securityInfo = null; try { ObjectMapper mapper = new ObjectMapper(); securityInfo = mapper.readValue(json, AuthenticationInfo.class); } catch (Exception e) { logger.error(MessageFormat.format( "Internal Error. Could not load from JSON: {0}", e.getMessage())); logger.debug(MessageFormat.format("json input= {0}", json)); } return securityInfo; } /** * Serialize the TungstenProperties into a JSON String * * @param prettyPrint Set to true to have the JSON output formatted for * easier read * @return String representing JSON serialization of the TungstenProperties * @throws JsonGenerationException * @throws JsonMappingException * @throws IOException */ public String toJSON() { String json = null; try { json = this.toJSON(false); } catch (Exception e) { logger.error("Could not Serialize into JSON:", e); } return json; } public String toJSON(boolean prettyPrint) throws JsonGenerationException, JsonMappingException, IOException { String json = null; ObjectMapper mapper = new ObjectMapper(); // Setup Jackson mapper.configure(Feature.INDENT_OUTPUT, true); mapper.configure(Feature.SORT_PROPERTIES_ALPHABETICALLY, true); ObjectWriter writer = mapper.writer(); if (prettyPrint) writer = writer.withDefaultPrettyPrinter(); json = writer.writeValueAsString(this); return json; } /** * {@inheritDoc} * * @see java.lang.Object#toString() */ public String toString() { StringBuilder strAuthInfo = new StringBuilder(); strAuthInfo.append(MessageFormat.format( "------------------------------------------------------------------- ### security.properties ### {0}\n", this.getTungstenApplicationName())); switch (tungstenApplicationName) { case ANY : strAuthInfo.append(MessageFormat.format("\t\t\t\t{0}={1}\n", SecurityConf.SECURITY_JMX_USE_ENCRYPTION, this.isEncryptionNeeded())); strAuthInfo.append(MessageFormat.format("\t\t\t\t{0}={1}\n", SecurityConf.SECURITY_JMX_USE_AUTHENTICATION, this.isAuthenticationNeeded())); strAuthInfo.append(MessageFormat.format("\t\t\t\t{0}={1}\n", SecurityConf.SECURITY_JMX_USE_TUNGSTEN_AUTHENTICATION_REALM_ENCRYPTED_PASSWORD, this.useEncryptedPasswords)); break; } strAuthInfo.append( "\t\t\t\t-------------------------------------------------------------------"); return strAuthInfo.toString(); } /** * Silently tries to close an InputStream. * * @param in */ private void closeInputStream(InputStream in) { try { in.close(); } catch (Exception e) { // Nothing to do, it's a last chance close } } /** * {@inheritDoc} This is used in SecurityHelperTest * * @see java.lang.Object#clone() */ public Object clone() { AuthenticationInfo authInfo = null; try { authInfo = (AuthenticationInfo) super.clone(); } catch (CloneNotSupportedException cnse) { cnse.printStackTrace(System.err); } return authInfo; } }