Thanks for reviewing. Good catch, a null check is needed to prevent NPEs. But null passwords are possible so perhaps make it like this:
return password == null ? null : password.toCharArray(); > On Sep 26, 2017, at 1:08, Gary Gregory <[email protected]> wrote: > >> On Mon, Sep 25, 2017 at 10:00 AM, <[email protected]> wrote: >> >> Repository: logging-log4j2 >> Updated Branches: >> refs/heads/master a73fce2e7 -> 08077cba3 >> >> >> LOG4J2-2054 Provide ways to configure SSL that avoid plain-text passwords >> in the log4j configuration. The configuration may now specify a system >> environment variable that holds the password, or the path to a file that >> holds the password. >> >> >> Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo >> Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/ >> commit/08077cba >> Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/08077cba >> Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/08077cba >> >> Branch: refs/heads/master >> Commit: 08077cba385ee376aa44ae33c66833421e9d19bc >> Parents: a73fce2 >> Author: rpopma <[email protected]> >> Authored: Tue Sep 26 01:00:15 2017 +0900 >> Committer: rpopma <[email protected]> >> Committed: Tue Sep 26 01:00:15 2017 +0900 >> >> ---------------------------------------------------------------------- >> .../net/ssl/EnvironmentPasswordProvider.java | 54 ++++++ >> .../core/net/ssl/FilePasswordProvider.java | 83 +++++++++ >> .../core/net/ssl/KeyStoreConfiguration.java | 58 +++++-- >> .../core/net/ssl/MemoryPasswordProvider.java | 20 ++- >> .../core/net/ssl/TrustStoreConfiguration.java | 57 ++++-- >> .../log4j/core/appender/HttpAppenderTest.java | 6 +- >> .../SecureSocketAppenderSocketOptionsTest.java | 8 +- >> .../core/appender/TlsSyslogAppenderTest.java | 4 +- >> .../ssl/EnvironmentPasswordProviderTest.java | 38 ++++ >> .../core/net/ssl/FilePasswordProviderTest.java | 50 ++++++ >> .../core/net/ssl/KeyStoreConfigurationTest.java | 8 +- >> .../net/ssl/MemoryPasswordProviderTest.java | 49 ++++++ >> .../core/net/ssl/SslConfigurationTest.java | 16 +- >> .../log4j/core/net/ssl/TestConstants.java | 10 +- >> .../net/ssl/TrustStoreConfigurationTest.java | 8 +- >> src/changes/changes.xml | 3 + >> src/site/site.xml | 1 + >> src/site/xdoc/manual/appenders.xml | 172 +++++++++++++++++-- >> 18 files changed, 580 insertions(+), 65 deletions(-) >> ---------------------------------------------------------------------- >> >> >> http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/ >> 08077cba/log4j-core/src/main/java/org/apache/logging/log4j/core/net/ssl/ >> EnvironmentPasswordProvider.java >> ---------------------------------------------------------------------- >> diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/ >> net/ssl/EnvironmentPasswordProvider.java b/log4j-core/src/main/java/ >> org/apache/logging/log4j/core/net/ssl/EnvironmentPasswordProvider.java >> new file mode 100644 >> index 0000000..e501c15 >> --- /dev/null >> +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/net/ssl/ >> EnvironmentPasswordProvider.java >> @@ -0,0 +1,54 @@ >> +/* >> + * 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.logging.log4j.core.net.ssl; >> + >> +import java.util.Objects; >> + >> +/** >> + * PasswordProvider implementation that obtains the password value from a >> system environment variable. >> + * <p> >> + * This implementation is not very secure because the Java interface to >> obtain system environment variable values >> + * requires us to use String objects. String objects are immutable and >> Java does not provide a way to erase this >> + * sensitive data from the application memory. The password data will >> stay resident in memory until the String object >> + * and its associated char[] array object are garbage collected and the >> memory is overwritten by another object. >> + * </p><p> >> + * This is slightly more secure than {@link MemoryPasswordProvider} >> because the actual password string is not pulled >> + * into memory until it is needed (so the password string does not need >> to be passed in from the command line or in a >> + * configuration file). >> + * This gives an attacker a smaller window of opportunity to obtain the >> password from a memory dump. >> + * </p><p> >> + * A more secure implementation is {@link FilePasswordProvider}. >> + * </p> >> + */ >> +class EnvironmentPasswordProvider implements PasswordProvider { >> + private final String passwordEnvironmentVariable; >> + >> + /** >> + * Constructs a new EnvironmentPasswordProvider with the specified >> environment variable name >> + * @param passwordEnvironmentVariable name of the system environment >> variable that holds the password >> + */ >> + public EnvironmentPasswordProvider(final String >> passwordEnvironmentVariable) { >> + this.passwordEnvironmentVariable = Objects.requireNonNull( >> + passwordEnvironmentVariable, >> "passwordEnvironmentVariable"); >> + } >> + >> + @Override >> + public char[] getPassword() { >> + String password = System.getenv(passwordEnvironmentVariable); >> + return password.toCharArray(); >> > > Needs a null check IMO with throws IllegalArgumentException message. > > Gary > > >> + } >> +} > > >> http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/ >> 08077cba/log4j-core/src/main/java/org/apache/logging/log4j/core/net/ssl/ >> FilePasswordProvider.java >> ---------------------------------------------------------------------- >> diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/ >> net/ssl/FilePasswordProvider.java b/log4j-core/src/main/java/ >> org/apache/logging/log4j/core/net/ssl/FilePasswordProvider.java >> new file mode 100644 >> index 0000000..ff59b00 >> --- /dev/null >> +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/ >> net/ssl/FilePasswordProvider.java >> @@ -0,0 +1,83 @@ >> +/* >> + * 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.logging.log4j.core.net.ssl; >> + >> +import java.io.IOException; >> +import java.nio.ByteBuffer; >> +import java.nio.CharBuffer; >> +import java.nio.charset.Charset; >> +import java.nio.file.Files; >> +import java.nio.file.NoSuchFileException; >> +import java.nio.file.Path; >> +import java.nio.file.Paths; >> +import java.util.Arrays; >> + >> +/** >> + * PasswordProvider that reads password from a file. >> + * <p> >> + * This is a relatively secure way to handle passwords: >> + * <ul> >> + * <li>Managing file access privileges can be delegated to the >> operating system.</li> >> + * <li>The password file can be in a separate location from the >> logging configuration. >> + * This gives flexibility to have different passwords in different >> environments while >> + * using the same logging configuration. It also allows for >> separation of responsibilities: >> + * developers don't need to know the password that is used in the >> production environment.</li> >> + * <li>There is only a small window of opportunity for attackers to >> obtain the password from a memory >> + * dump: the password data is only resident in memory from the >> moment the caller calls the >> + * {@link #getPassword()} method and the password file is read >> until the moment that the caller >> + * completes authentication and overwrites the password char[] >> array.</li> >> + * </ul> >> + * </p><p> >> + * Less secure implementations are {@link MemoryPasswordProvider} and >> {@link EnvironmentPasswordProvider}. >> + * </p> >> + */ >> +class FilePasswordProvider implements PasswordProvider { >> + private final Path passwordPath; >> + >> + /** >> + * Constructs a new FilePasswordProvider with the specified path. >> + * @param passwordFile the path to the password file >> + * @throws NoSuchFileException if the password file does not exist >> when this FilePasswordProvider is constructed >> + */ >> + public FilePasswordProvider(final String passwordFile) throws >> NoSuchFileException { >> + this.passwordPath = Paths.get(passwordFile); >> + if (!Files.exists(passwordPath)) { >> + throw new NoSuchFileException("PasswordFile '" + >> passwordFile + "' does not exist"); >> + } >> + } >> + >> + @Override >> + public char[] getPassword() { >> + byte[] bytes = null; >> + try { >> + bytes = Files.readAllBytes(passwordPath); >> + ByteBuffer bb = ByteBuffer.wrap(bytes); >> + CharBuffer decoded = Charset.defaultCharset().decode(bb); >> + char[] result = new char[decoded.limit()]; >> + decoded.get(result, 0, result.length); >> + decoded.rewind(); >> + decoded.put(new char[result.length]); // erase decoded >> CharBuffer >> + return result; >> + } catch (IOException e) { >> + throw new IllegalStateException("Could not read password from >> " + passwordPath + ": " + e, e); >> + } finally { >> + if (bytes != null) { >> + Arrays.fill(bytes, (byte) 0x0); >> + } >> + } >> + } >> +} >> >> http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/ >> 08077cba/log4j-core/src/main/java/org/apache/logging/log4j/core/net/ssl/ >> KeyStoreConfiguration.java >> ---------------------------------------------------------------------- >> diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/ >> net/ssl/KeyStoreConfiguration.java b/log4j-core/src/main/java/ >> org/apache/logging/log4j/core/net/ssl/KeyStoreConfiguration.java >> index 3fc37bd..d0c7bb0 100644 >> --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/ >> net/ssl/KeyStoreConfiguration.java >> +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/ >> net/ssl/KeyStoreConfiguration.java >> @@ -59,6 +59,9 @@ public class KeyStoreConfiguration extends >> AbstractKeyStoreConfiguration { >> final String keyStoreType, >> final String keyManagerFactoryAlgorithm) >> throws StoreConfigurationException { >> this(location, new MemoryPasswordProvider(password), >> keyStoreType, keyManagerFactoryAlgorithm); >> + if (password != null) { >> + Arrays.fill(password, '\0'); >> + } >> } >> >> /** >> @@ -92,24 +95,54 @@ public class KeyStoreConfiguration extends >> AbstractKeyStoreConfiguration { >> // @formatter:off >> @PluginAttribute("location") final String location, >> @PluginAttribute(value = "password", sensitive = true) final >> char[] password, >> + @PluginAttribute("passwordEnvironmentVariable") final String >> passwordEnvironmentVariable, >> + @PluginAttribute("passwordFile") final String passwordFile, >> @PluginAttribute("type") final String keyStoreType, >> @PluginAttribute("keyManagerFactoryAlgorithm") final String >> keyManagerFactoryAlgorithm) throws StoreConfigurationException { >> // @formatter:on >> - return new KeyStoreConfiguration(location, new >> MemoryPasswordProvider(password), keyStoreType, >> - keyManagerFactoryAlgorithm); >> + >> + if (password != null && passwordEnvironmentVariable != null && >> passwordFile != null) { >> + throw new StoreConfigurationException("You MUST set only one >> of 'password', 'passwordEnvironmentVariable' or 'passwordFile'."); >> + } >> + try { >> + // @formatter:off >> + PasswordProvider provider = passwordFile != null >> + ? new FilePasswordProvider(passwordFile) >> + : passwordEnvironmentVariable != null >> + ? new EnvironmentPasswordProvider( >> passwordEnvironmentVariable) >> + // the default is memory char[] array, which >> may be null >> + : new MemoryPasswordProvider(password); >> + // @formatter:on >> + if (password != null) { >> + Arrays.fill(password, '\0'); >> + } >> + return new KeyStoreConfiguration(location, provider, >> keyStoreType, keyManagerFactoryAlgorithm); >> + } catch (Exception ex) { >> + throw new StoreConfigurationException("Could not configure >> KeyStore", ex); >> + } >> + } >> + >> + /** >> + * @deprecated use {@link #createKeyStoreConfiguration(String, >> char[], String, String, String, String)} >> + */ >> + public static KeyStoreConfiguration createKeyStoreConfiguration( >> + // @formatter:off >> + final String location, >> + final char[] password, >> + final String keyStoreType, >> + final String keyManagerFactoryAlgorithm) throws >> StoreConfigurationException { >> + // @formatter:on >> + return createKeyStoreConfiguration(location, password, null, >> null, keyStoreType, keyManagerFactoryAlgorithm); >> } >> >> /** >> * Creates a KeyStoreConfiguration. >> * >> - * @param location >> - * The location of the KeyStore, a file path, URL or resource. >> - * @param password >> - * The password to access the KeyStore. >> - * @param keyStoreType >> - * The KeyStore type, null defaults to {@code "JKS"}. >> - * @param keyManagerFactoryAlgorithm >> - * The standard name of the requested algorithm. See the Java >> Secure Socket Extension Reference Guide for information about these names. >> + * @param location The location of the KeyStore, a file path, URL or >> resource. >> + * @param password The password to access the KeyStore. >> + * @param keyStoreType The KeyStore type, null defaults to {@code >> "JKS"}. >> + * @param keyManagerFactoryAlgorithm The standard name of the >> requested algorithm. See the Java Secure Socket >> + * Extension Reference Guide for information about these names. >> * @return a new KeyStoreConfiguration >> * @throws StoreConfigurationException Thrown if this call cannot >> load the KeyStore. >> * @deprecated Use createKeyStoreConfiguration(String, char[], >> String, String) >> @@ -122,8 +155,9 @@ public class KeyStoreConfiguration extends >> AbstractKeyStoreConfiguration { >> final String keyStoreType, >> final String keyManagerFactoryAlgorithm) throws >> StoreConfigurationException { >> // @formatter:on >> - return new KeyStoreConfiguration(location, >> - new MemoryPasswordProvider(password == null ? null : >> password.toCharArray()), keyStoreType, >> + return createKeyStoreConfiguration(location, >> + (password == null ? null : password.toCharArray()), >> + keyStoreType, >> keyManagerFactoryAlgorithm); >> } >> >> >> http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/ >> 08077cba/log4j-core/src/main/java/org/apache/logging/log4j/core/net/ssl/ >> MemoryPasswordProvider.java >> ---------------------------------------------------------------------- >> diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/ >> net/ssl/MemoryPasswordProvider.java b/log4j-core/src/main/java/ >> org/apache/logging/log4j/core/net/ssl/MemoryPasswordProvider.java >> index 328728d..6fd7ab4 100644 >> --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/net/ssl/ >> MemoryPasswordProvider.java >> +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/net/ssl/ >> MemoryPasswordProvider.java >> @@ -16,14 +16,26 @@ >> */ >> package org.apache.logging.log4j.core.net.ssl; >> >> +import java.util.Arrays; >> + >> /** >> - * Simple (and not very secure) PasswordProvider implementation that >> keeps the password char[] array in memory. >> + * Simple PasswordProvider implementation that keeps the password char[] >> array in memory. >> + * <p> >> + * This implementation is not very secure because the password data is >> resident in memory during the life of this >> + * provider object, giving attackers a large window of opportunity to >> obtain the password from a memory dump. >> + * A slightly more secure implementation is {@link >> EnvironmentPasswordProvider}, >> + * and an even more secure implementation is {@link FilePasswordProvider}. >> + * </p> >> */ >> class MemoryPasswordProvider implements PasswordProvider { >> private final char[] password; >> >> public MemoryPasswordProvider(final char[] chars) { >> - password = chars; >> + if (chars != null) { >> + password = chars.clone(); >> + } else { >> + password = null; >> + } >> } >> >> @Override >> @@ -33,4 +45,8 @@ class MemoryPasswordProvider implements PasswordProvider >> { >> } >> return password.clone(); >> } >> + >> + public void clearSecrets() { >> + Arrays.fill(password, '\0'); >> + } >> } >> >> http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/ >> 08077cba/log4j-core/src/main/java/org/apache/logging/log4j/core/net/ssl/ >> TrustStoreConfiguration.java >> ---------------------------------------------------------------------- >> diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/ >> net/ssl/TrustStoreConfiguration.java b/log4j-core/src/main/java/ >> org/apache/logging/log4j/core/net/ssl/TrustStoreConfiguration.java >> index c472186..d884aed 100644 >> --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/net/ssl/ >> TrustStoreConfiguration.java >> +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/net/ssl/ >> TrustStoreConfiguration.java >> @@ -18,6 +18,7 @@ package org.apache.logging.log4j.core.net.ssl; >> >> import java.security.KeyStoreException; >> import java.security.NoSuchAlgorithmException; >> +import java.util.Arrays; >> >> import javax.net.ssl.TrustManagerFactory; >> >> @@ -50,6 +51,9 @@ public class TrustStoreConfiguration extends >> AbstractKeyStoreConfiguration { >> public TrustStoreConfiguration(final String location, final char[] >> password, final String keyStoreType, >> final String trustManagerFactoryAlgorithm) throws >> StoreConfigurationException { >> this(location, new MemoryPasswordProvider(password), >> keyStoreType, trustManagerFactoryAlgorithm); >> + if (password != null) { >> + Arrays.fill(password, '\0'); >> + } >> } >> >> /** >> @@ -81,24 +85,54 @@ public class TrustStoreConfiguration extends >> AbstractKeyStoreConfiguration { >> // @formatter:off >> @PluginAttribute("location") final String location, >> @PluginAttribute(value = "password", sensitive = true) final >> char[] password, >> + @PluginAttribute("passwordEnvironmentVariable") final String >> passwordEnvironmentVariable, >> + @PluginAttribute("passwordFile") final String passwordFile, >> @PluginAttribute("type") final String keyStoreType, >> @PluginAttribute("trustManagerFactoryAlgorithm") final >> String trustManagerFactoryAlgorithm) throws StoreConfigurationException { >> // @formatter:on >> - return new TrustStoreConfiguration(location, new >> MemoryPasswordProvider(password), keyStoreType, >> - trustManagerFactoryAlgorithm); >> + >> + if (password != null && passwordEnvironmentVariable != null && >> passwordFile != null) { >> + throw new IllegalStateException("You MUST set only one of >> 'password', 'passwordEnvironmentVariable' or 'passwordFile'."); >> + } >> + try { >> + // @formatter:off >> + PasswordProvider provider = passwordFile != null >> + ? new FilePasswordProvider(passwordFile) >> + : passwordEnvironmentVariable != null >> + ? new EnvironmentPasswordProvider( >> passwordEnvironmentVariable) >> + // the default is memory char[] array, which >> may be null >> + : new MemoryPasswordProvider(password); >> + // @formatter:on >> + if (password != null) { >> + Arrays.fill(password, '\0'); >> + } >> + return new TrustStoreConfiguration(location, provider, >> keyStoreType, trustManagerFactoryAlgorithm); >> + } catch (Exception ex) { >> + throw new StoreConfigurationException("Could not configure >> TrustStore", ex); >> + } >> + } >> + >> + /** >> + * @deprecated Use {@link #createKeyStoreConfiguration(String, >> char[], String, String, String, String)} >> + */ >> + public static TrustStoreConfiguration createKeyStoreConfiguration( >> + // @formatter:off >> + final String location, >> + final char[] password, >> + final String keyStoreType, >> + final String trustManagerFactoryAlgorithm) throws >> StoreConfigurationException { >> + // @formatter:on >> + return createKeyStoreConfiguration(location, password, null, >> null, keyStoreType, trustManagerFactoryAlgorithm); >> } >> >> /** >> * Creates a KeyStoreConfiguration. >> * >> - * @param location >> - * The location of the KeyStore, a file path, URL or resource. >> - * @param password >> - * The password to access the KeyStore. >> - * @param keyStoreType >> - * The KeyStore type, null defaults to {@code "JKS"}. >> - * @param trustManagerFactoryAlgorithm >> - * The standard name of the requested trust management >> algorithm. See the Java Secure Socket Extension Reference Guide for >> information these names. >> + * @param location The location of the KeyStore, a file path, URL or >> resource. >> + * @param password The password to access the KeyStore. >> + * @param keyStoreType The KeyStore type, null defaults to {@code >> "JKS"}. >> + * @param trustManagerFactoryAlgorithm The standard name of the >> requested trust management algorithm. See the Java >> + * Secure Socket Extension Reference Guide for information these >> names. >> * @return a new TrustStoreConfiguration >> * @throws StoreConfigurationException Thrown if this instance cannot >> load the KeyStore. >> * @deprecated Use createKeyStoreConfiguration(String, char[], >> String, String) >> @@ -111,7 +145,8 @@ public class TrustStoreConfiguration extends >> AbstractKeyStoreConfiguration { >> final String keyStoreType, >> final String trustManagerFactoryAlgorithm) throws >> StoreConfigurationException { >> // @formatter:on >> - return new TrustStoreConfiguration(location, password, >> keyStoreType, trustManagerFactoryAlgorithm); >> + return createKeyStoreConfiguration(location, (password == null ? >> null : password.toCharArray()), >> + null, null, keyStoreType, trustManagerFactoryAlgorithm); >> } >> >> public TrustManagerFactory initTrustManagerFactory() throws >> NoSuchAlgorithmException, KeyStoreException { >> >> http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/ >> 08077cba/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/ >> HttpAppenderTest.java >> ---------------------------------------------------------------------- >> diff --git >> a/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/HttpAppenderTest.java >> b/log4j-core/src/test/java/org/apache/logging/log4j/core/ >> appender/HttpAppenderTest.java >> index 337a0c0..c50c8ce 100644 >> --- a/log4j-core/src/test/java/org/apache/logging/log4j/core/ >> appender/HttpAppenderTest.java >> +++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/ >> appender/HttpAppenderTest.java >> @@ -82,7 +82,7 @@ public class HttpAppenderTest { >> @Rule >> public WireMockRule wireMockRule = new WireMockRule(wireMockConfig(). >> dynamicPort().dynamicHttpsPort() >> .keystorePath(TestConstants.KEYSTORE_FILE) >> - .keystorePassword(String.valueOf(TestConstants.KEYSTORE_PWD)) >> + .keystorePassword(String.valueOf(TestConstants.KEYSTORE_PWD())) >> .keystoreType(TestConstants.KEYSTORE_TYPE)); >> >> @Test >> @@ -115,8 +115,8 @@ public class HttpAppenderTest { >> .setConfiguration(ctx.getConfiguration()) >> .setUrl(new URL("https://localhost:" + >> wireMockRule.httpsPort() + "/test/log4j/")) >> .setSslConfiguration(SslConfiguration. >> createSSLConfiguration(null, >> - >> KeyStoreConfiguration.createKeyStoreConfiguration(TestConstants.KEYSTORE_FILE, >> TestConstants.KEYSTORE_PWD, TestConstants.KEYSTORE_TYPE, null), >> - >> TrustStoreConfiguration.createKeyStoreConfiguration(TestConstants.TRUSTSTORE_FILE, >> TestConstants.TRUSTSTORE_PWD, TestConstants.TRUSTSTORE_TYPE, null))) >> + >> KeyStoreConfiguration.createKeyStoreConfiguration(TestConstants.KEYSTORE_FILE, >> TestConstants.KEYSTORE_PWD(), TestConstants.KEYSTORE_TYPE, null), >> + >> TrustStoreConfiguration.createKeyStoreConfiguration(TestConstants.TRUSTSTORE_FILE, >> TestConstants.TRUSTSTORE_PWD(), TestConstants.TRUSTSTORE_TYPE, null))) >> .setVerifyHostname(false) >> .build(); >> appender.append(createLogEvent()); >> >> http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/ >> 08077cba/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/ >> SecureSocketAppenderSocketOptionsTest.java >> ---------------------------------------------------------------------- >> diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/ >> appender/SecureSocketAppenderSocketOptionsTest.java >> b/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/ >> SecureSocketAppenderSocketOptionsTest.java >> index b92e393..abee218 100644 >> --- a/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/ >> SecureSocketAppenderSocketOptionsTest.java >> +++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/ >> SecureSocketAppenderSocketOptionsTest.java >> @@ -75,13 +75,17 @@ public class SecureSocketAppenderSocketOptionsTest { >> public static void initServerSocketFactory() throws >> StoreConfigurationException { >> final KeyStoreConfiguration ksc = KeyStoreConfiguration. >> createKeyStoreConfiguration( >> TestConstants.KEYSTORE_FILE, // file >> - TestConstants.KEYSTORE_PWD, // password >> + TestConstants.KEYSTORE_PWD(), // password >> + null, // passwordEnvironmentVariable >> + null, // passwordFile >> null, // key store type >> null); // algorithm >> >> final TrustStoreConfiguration tsc = TrustStoreConfiguration. >> createKeyStoreConfiguration( >> TestConstants.TRUSTSTORE_FILE, // file >> - TestConstants.TRUSTSTORE_PWD, // password >> + TestConstants.TRUSTSTORE_PWD(), // password >> + null, // passwordEnvironmentVariable >> + null, // passwordFile >> null, // key store type >> null); // algorithm >> sslConfiguration = SslConfiguration.createSSLConfiguration(null, >> ksc, tsc); >> >> http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/ >> 08077cba/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/ >> TlsSyslogAppenderTest.java >> ---------------------------------------------------------------------- >> diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/ >> appender/TlsSyslogAppenderTest.java b/log4j-core/src/test/java/ >> org/apache/logging/log4j/core/appender/TlsSyslogAppenderTest.java >> index e025fd8..ae567a0 100644 >> --- a/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/ >> TlsSyslogAppenderTest.java >> +++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/ >> TlsSyslogAppenderTest.java >> @@ -78,8 +78,8 @@ public class TlsSyslogAppenderTest extends >> SyslogAppenderTest { >> } >> >> private void initServerSocketFactory() throws >> StoreConfigurationException { >> - final KeyStoreConfiguration ksc = new >> KeyStoreConfiguration(TestConstants.KEYSTORE_FILE, >> TestConstants.KEYSTORE_PWD, null, null); >> - final TrustStoreConfiguration tsc = new >> TrustStoreConfiguration(TestConstants.TRUSTSTORE_FILE, >> TestConstants.TRUSTSTORE_PWD, null, null); >> + final KeyStoreConfiguration ksc = new >> KeyStoreConfiguration(TestConstants.KEYSTORE_FILE, >> TestConstants.KEYSTORE_PWD(), null, null); >> + final TrustStoreConfiguration tsc = new >> TrustStoreConfiguration(TestConstants.TRUSTSTORE_FILE, >> TestConstants.TRUSTSTORE_PWD(), null, null); >> sslConfiguration = SslConfiguration.createSSLConfiguration(null, >> ksc, tsc); >> serverSocketFactory = sslConfiguration. >> getSslServerSocketFactory(); >> } >> >> http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/ >> 08077cba/log4j-core/src/test/java/org/apache/logging/log4j/core/net/ssl/ >> EnvironmentPasswordProviderTest.java >> ---------------------------------------------------------------------- >> diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/ >> net/ssl/EnvironmentPasswordProviderTest.java b/log4j-core/src/test/java/ >> org/apache/logging/log4j/core/net/ssl/EnvironmentPasswordProviderTest.java >> new file mode 100644 >> index 0000000..a9b266f >> --- /dev/null >> +++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/net/ssl/ >> EnvironmentPasswordProviderTest.java >> @@ -0,0 +1,38 @@ >> +package org.apache.logging.log4j.core.net.ssl;/* >> + * 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. >> + */ >> + >> +import org.junit.Test; >> + >> +import static org.junit.Assert.*; >> + >> +public class EnvironmentPasswordProviderTest { >> + >> + @Test(expected = NullPointerException.class) >> + public void testConstructorDisallowsNull() { >> + new EnvironmentPasswordProvider(null); >> + } >> + >> + @Test >> + public void testGetPasswordReturnsEnvironmentVariableValue() { >> + final String value = System.getenv("PATH"); >> + if (value == null) { >> + return; // we cannot test in this environment >> + } >> + final char[] actual = new EnvironmentPasswordProvider(" >> PATH").getPassword(); >> + assertArrayEquals(value.toCharArray(), actual); >> + } >> +} >> \ No newline at end of file >> >> http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/ >> 08077cba/log4j-core/src/test/java/org/apache/logging/log4j/core/net/ssl/ >> FilePasswordProviderTest.java >> ---------------------------------------------------------------------- >> diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/ >> net/ssl/FilePasswordProviderTest.java b/log4j-core/src/test/java/ >> org/apache/logging/log4j/core/net/ssl/FilePasswordProviderTest.java >> new file mode 100644 >> index 0000000..eaa2d82 >> --- /dev/null >> +++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/net/ssl/ >> FilePasswordProviderTest.java >> @@ -0,0 +1,50 @@ >> +package org.apache.logging.log4j.core.net.ssl;/* >> + * 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. >> + */ >> + >> +import java.nio.charset.Charset; >> +import java.nio.file.Files; >> +import java.nio.file.NoSuchFileException; >> +import java.nio.file.Path; >> +import java.util.Arrays; >> + >> +import org.junit.Test; >> + >> +import static org.junit.Assert.*; >> + >> +public class FilePasswordProviderTest { >> + >> + @Test >> + public void testGetPassword() throws Exception { >> + final String PASSWORD = "myPass123"; >> + final Path path = Files.createTempFile("testPass", ".txt"); >> + Files.write(path, PASSWORD.getBytes(Charset.defaultCharset())); >> + >> + char[] actual = new FilePasswordProvider(path. >> toString()).getPassword(); >> + Files.delete(path); >> + assertArrayEquals(PASSWORD.toCharArray(), actual); >> + } >> + >> + @Test(expected = NullPointerException.class) >> + public void testConstructorDisallowsNull() throws Exception { >> + new FilePasswordProvider(null); >> + } >> + >> + @Test(expected = NoSuchFileException.class) >> + public void testConstructorFailsIfFileDoesNotExist() throws >> Exception { >> + new FilePasswordProvider("nosuchfile"); >> + } >> +} >> >> http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/ >> 08077cba/log4j-core/src/test/java/org/apache/logging/log4j/core/net/ssl/ >> KeyStoreConfigurationTest.java >> ---------------------------------------------------------------------- >> diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/ >> net/ssl/KeyStoreConfigurationTest.java b/log4j-core/src/test/java/ >> org/apache/logging/log4j/core/net/ssl/KeyStoreConfigurationTest.java >> index ef38483..d5761ac 100644 >> --- a/log4j-core/src/test/java/org/apache/logging/log4j/core/net/ssl/ >> KeyStoreConfigurationTest.java >> +++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/net/ssl/ >> KeyStoreConfigurationTest.java >> @@ -37,7 +37,7 @@ public class KeyStoreConfigurationTest { >> >> @Test >> public void loadNotEmptyConfigurationDeprecated() throws >> StoreConfigurationException { >> - final KeyStoreConfiguration ksc = new >> KeyStoreConfiguration(TestConstants.KEYSTORE_FILE, >> TestConstants.KEYSTORE_PWD, >> + final KeyStoreConfiguration ksc = new >> KeyStoreConfiguration(TestConstants.KEYSTORE_FILE, >> TestConstants.KEYSTORE_PWD(), >> TestConstants.KEYSTORE_TYPE, null); >> final KeyStore ks = ksc.getKeyStore(); >> Assert.assertTrue(ks != null); >> @@ -45,7 +45,7 @@ public class KeyStoreConfigurationTest { >> >> @Test >> public void loadNotEmptyConfiguration() throws >> StoreConfigurationException { >> - final KeyStoreConfiguration ksc = new >> KeyStoreConfiguration(TestConstants.KEYSTORE_FILE, >> new MemoryPasswordProvider(TestConstants.KEYSTORE_PWD), >> + final KeyStoreConfiguration ksc = new >> KeyStoreConfiguration(TestConstants.KEYSTORE_FILE, >> new MemoryPasswordProvider(TestConstants.KEYSTORE_PWD()), >> TestConstants.KEYSTORE_TYPE, null); >> final KeyStore ks = ksc.getKeyStore(); >> Assert.assertTrue(ks != null); >> @@ -53,7 +53,7 @@ public class KeyStoreConfigurationTest { >> >> @Test >> public void returnTheSameKeyStoreAfterMultipleLoadsDeprecated() >> throws StoreConfigurationException { >> - final KeyStoreConfiguration ksc = new >> KeyStoreConfiguration(TestConstants.KEYSTORE_FILE, >> TestConstants.KEYSTORE_PWD, >> + final KeyStoreConfiguration ksc = new >> KeyStoreConfiguration(TestConstants.KEYSTORE_FILE, >> TestConstants.KEYSTORE_PWD(), >> TestConstants.KEYSTORE_TYPE, null); >> final KeyStore ks = ksc.getKeyStore(); >> final KeyStore ks2 = ksc.getKeyStore(); >> @@ -62,7 +62,7 @@ public class KeyStoreConfigurationTest { >> >> @Test >> public void returnTheSameKeyStoreAfterMultipleLoads() throws >> StoreConfigurationException { >> - final KeyStoreConfiguration ksc = new >> KeyStoreConfiguration(TestConstants.KEYSTORE_FILE, >> new MemoryPasswordProvider(TestConstants.KEYSTORE_PWD), >> + final KeyStoreConfiguration ksc = new >> KeyStoreConfiguration(TestConstants.KEYSTORE_FILE, >> new MemoryPasswordProvider(TestConstants.KEYSTORE_PWD()), >> TestConstants.KEYSTORE_TYPE, null); >> final KeyStore ks = ksc.getKeyStore(); >> final KeyStore ks2 = ksc.getKeyStore(); >> >> http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/ >> 08077cba/log4j-core/src/test/java/org/apache/logging/log4j/core/net/ssl/ >> MemoryPasswordProviderTest.java >> ---------------------------------------------------------------------- >> diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/ >> net/ssl/MemoryPasswordProviderTest.java b/log4j-core/src/test/java/ >> org/apache/logging/log4j/core/net/ssl/MemoryPasswordProviderTest.java >> new file mode 100644 >> index 0000000..df4b5f2 >> --- /dev/null >> +++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/net/ssl/ >> MemoryPasswordProviderTest.java >> @@ -0,0 +1,49 @@ >> +package org.apache.logging.log4j.core.net.ssl;/* >> + * 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. >> + */ >> + >> +import java.util.Arrays; >> + >> +import org.junit.Test; >> + >> +import static org.junit.Assert.*; >> + >> +public class MemoryPasswordProviderTest { >> + @Test >> + public void testConstructorAllowsNull() { >> + assertEquals(null, new MemoryPasswordProvider(null). >> getPassword()); >> + } >> + >> + @Test >> + public void testConstructorDoesNotModifyOriginalParameterArray() { >> + char[] initial = "123".toCharArray(); >> + new MemoryPasswordProvider(initial); >> + assertArrayEquals("123".toCharArray(), initial); >> + } >> + >> + @Test >> + public void testGetPasswordReturnsCopyOfConstructorArray() { >> + char[] initial = "123".toCharArray(); >> + MemoryPasswordProvider provider = new MemoryPasswordProvider( >> initial); >> + char[] actual = provider.getPassword(); >> + assertArrayEquals("123".toCharArray(), actual); >> + assertNotSame(initial, actual); >> + >> + Arrays.fill(initial, 'a'); >> + assertArrayEquals("123".toCharArray(), provider.getPassword()); >> + assertNotSame(provider.getPassword(), provider.getPassword()); >> + } >> +} >> >> http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/ >> 08077cba/log4j-core/src/test/java/org/apache/logging/log4j/core/net/ssl/ >> SslConfigurationTest.java >> ---------------------------------------------------------------------- >> diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/ >> net/ssl/SslConfigurationTest.java b/log4j-core/src/test/java/ >> org/apache/logging/log4j/core/net/ssl/SslConfigurationTest.java >> index 936cc66..41349a0 100644 >> --- a/log4j-core/src/test/java/org/apache/logging/log4j/core/ >> net/ssl/SslConfigurationTest.java >> +++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/ >> net/ssl/SslConfigurationTest.java >> @@ -33,33 +33,33 @@ public class SslConfigurationTest { >> >> public static SslConfiguration >> createTestSslConfigurationResourcesDeprecated() >> throws StoreConfigurationException { >> final KeyStoreConfiguration ksc = new KeyStoreConfiguration( >> TestConstants.KEYSTORE_FILE_RESOURCE, >> - TestConstants.KEYSTORE_PWD, TestConstants.KEYSTORE_TYPE, >> null); >> + TestConstants.KEYSTORE_PWD(), >> TestConstants.KEYSTORE_TYPE, null); >> final TrustStoreConfiguration tsc = new TrustStoreConfiguration( >> TestConstants.TRUSTSTORE_FILE_RESOURCE, >> - TestConstants.TRUSTSTORE_PWD, null, null); >> + TestConstants.TRUSTSTORE_PWD(), null, null); >> return SslConfiguration.createSSLConfiguration(null, ksc, tsc); >> } >> >> public static SslConfiguration createTestSslConfigurationResources() >> throws StoreConfigurationException { >> final KeyStoreConfiguration ksc = new KeyStoreConfiguration( >> TestConstants.KEYSTORE_FILE_RESOURCE, >> - new MemoryPasswordProvider(TestConstants.KEYSTORE_PWD), >> TestConstants.KEYSTORE_TYPE, null); >> + new MemoryPasswordProvider(TestConstants.KEYSTORE_PWD()), >> TestConstants.KEYSTORE_TYPE, null); >> final TrustStoreConfiguration tsc = new TrustStoreConfiguration( >> TestConstants.TRUSTSTORE_FILE_RESOURCE, >> - new MemoryPasswordProvider(TestConstants.TRUSTSTORE_PWD), >> null, null); >> + new MemoryPasswordProvider(TestConstants.TRUSTSTORE_PWD()), >> null, null); >> return SslConfiguration.createSSLConfiguration(null, ksc, tsc); >> } >> >> public static SslConfiguration >> createTestSslConfigurationFilesDeprecated() >> throws StoreConfigurationException { >> final KeyStoreConfiguration ksc = new KeyStoreConfiguration( >> TestConstants.KEYSTORE_FILE, >> - TestConstants.KEYSTORE_PWD, TestConstants.KEYSTORE_TYPE, >> null); >> + TestConstants.KEYSTORE_PWD(), >> TestConstants.KEYSTORE_TYPE, null); >> final TrustStoreConfiguration tsc = new TrustStoreConfiguration( >> TestConstants.TRUSTSTORE_FILE, >> - TestConstants.TRUSTSTORE_PWD, null, null); >> + TestConstants.TRUSTSTORE_PWD(), null, null); >> return SslConfiguration.createSSLConfiguration(null, ksc, tsc); >> } >> >> public static SslConfiguration createTestSslConfigurationFiles() >> throws StoreConfigurationException { >> final KeyStoreConfiguration ksc = new KeyStoreConfiguration( >> TestConstants.KEYSTORE_FILE, >> - new MemoryPasswordProvider(TestConstants.KEYSTORE_PWD), >> TestConstants.KEYSTORE_TYPE, null); >> + new MemoryPasswordProvider(TestConstants.KEYSTORE_PWD()), >> TestConstants.KEYSTORE_TYPE, null); >> final TrustStoreConfiguration tsc = new TrustStoreConfiguration( >> TestConstants.TRUSTSTORE_FILE, >> - new MemoryPasswordProvider(TestConstants.TRUSTSTORE_PWD), >> null, null); >> + new MemoryPasswordProvider(TestConstants.TRUSTSTORE_PWD()), >> null, null); >> return SslConfiguration.createSSLConfiguration(null, ksc, tsc); >> } >> >> >> http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/ >> 08077cba/log4j-core/src/test/java/org/apache/logging/log4j/ >> core/net/ssl/TestConstants.java >> ---------------------------------------------------------------------- >> diff --git >> a/log4j-core/src/test/java/org/apache/logging/log4j/core/net/ssl/TestConstants.java >> b/log4j-core/src/test/java/org/apache/logging/log4j/core/ >> net/ssl/TestConstants.java >> index 1fa8572..90b3bed 100644 >> --- a/log4j-core/src/test/java/org/apache/logging/log4j/core/ >> net/ssl/TestConstants.java >> +++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/ >> net/ssl/TestConstants.java >> @@ -17,24 +17,24 @@ >> package org.apache.logging.log4j.core.net.ssl; >> >> public class TestConstants { >> - >> + >> public static final String SOURCE_FOLDER = "src/test/resources/"; >> public static final String RESOURCE_ROOT = "org/apache/logging/log4j/ >> core/net/ssl/"; >> - >> + >> public static final String PATH = SOURCE_FOLDER + RESOURCE_ROOT; >> public static final String TRUSTSTORE_PATH = PATH; >> public static final String TRUSTSTORE_RESOURCE = RESOURCE_ROOT; >> public static final String TRUSTSTORE_FILE = TRUSTSTORE_PATH + >> "truststore.jks"; >> public static final String TRUSTSTORE_FILE_RESOURCE = >> TRUSTSTORE_RESOURCE + "truststore.jks"; >> - public static final char[] TRUSTSTORE_PWD = "changeit".toCharArray(); >> + public static final char[] TRUSTSTORE_PWD() { return >> "changeit".toCharArray(); } >> public static final String TRUSTSTORE_TYPE = "JKS"; >> >> public static final String KEYSTORE_PATH = PATH; >> public static final String KEYSTORE_RESOURCE = RESOURCE_ROOT; >> public static final String KEYSTORE_FILE = KEYSTORE_PATH + >> "client.log4j2-keystore.jks"; >> public static final String KEYSTORE_FILE_RESOURCE = KEYSTORE_RESOURCE >> + "client.log4j2-keystore.jks"; >> - public static final char[] KEYSTORE_PWD = "changeit".toCharArray(); >> + public static final char[] KEYSTORE_PWD() { return >> "changeit".toCharArray(); } >> public static final String KEYSTORE_TYPE = "JKS"; >> - >> + >> public static final char[] NULL_PWD = null; >> } >> >> http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/ >> 08077cba/log4j-core/src/test/java/org/apache/logging/log4j/core/net/ssl/ >> TrustStoreConfigurationTest.java >> ---------------------------------------------------------------------- >> diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/ >> net/ssl/TrustStoreConfigurationTest.java b/log4j-core/src/test/java/ >> org/apache/logging/log4j/core/net/ssl/TrustStoreConfigurationTest.java >> index 14c58bb..d27a1fd 100644 >> --- a/log4j-core/src/test/java/org/apache/logging/log4j/core/net/ssl/ >> TrustStoreConfigurationTest.java >> +++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/net/ssl/ >> TrustStoreConfigurationTest.java >> @@ -37,21 +37,21 @@ public class TrustStoreConfigurationTest { >> >> @Test >> public void loadConfigurationDeprecated() throws >> StoreConfigurationException { >> - final TrustStoreConfiguration ksc = new >> TrustStoreConfiguration(TestConstants.TRUSTSTORE_FILE, >> TestConstants.TRUSTSTORE_PWD, null, null); >> + final TrustStoreConfiguration ksc = new >> TrustStoreConfiguration(TestConstants.TRUSTSTORE_FILE, >> TestConstants.TRUSTSTORE_PWD(), null, null); >> final KeyStore ks = ksc.getKeyStore(); >> Assert.assertNotNull(ks); >> } >> >> @Test >> public void loadConfiguration() throws StoreConfigurationException { >> - final TrustStoreConfiguration ksc = new >> TrustStoreConfiguration(TestConstants.TRUSTSTORE_FILE, >> new MemoryPasswordProvider(TestConstants.TRUSTSTORE_PWD), null, null); >> + final TrustStoreConfiguration ksc = new >> TrustStoreConfiguration(TestConstants.TRUSTSTORE_FILE, >> new MemoryPasswordProvider(TestConstants.TRUSTSTORE_PWD()), null, null); >> final KeyStore ks = ksc.getKeyStore(); >> Assert.assertNotNull(ks); >> } >> >> @Test >> public void returnTheSameKeyStoreAfterMultipleLoadsDeprecated() >> throws StoreConfigurationException { >> - final TrustStoreConfiguration ksc = new >> TrustStoreConfiguration(TestConstants.TRUSTSTORE_FILE, >> TestConstants.TRUSTSTORE_PWD, null, null); >> + final TrustStoreConfiguration ksc = new >> TrustStoreConfiguration(TestConstants.TRUSTSTORE_FILE, >> TestConstants.TRUSTSTORE_PWD(), null, null); >> final KeyStore ks = ksc.getKeyStore(); >> final KeyStore ks2 = ksc.getKeyStore(); >> Assert.assertTrue(ks == ks2); >> @@ -59,7 +59,7 @@ public class TrustStoreConfigurationTest { >> >> @Test >> public void returnTheSameKeyStoreAfterMultipleLoads() throws >> StoreConfigurationException { >> - final TrustStoreConfiguration ksc = new >> TrustStoreConfiguration(TestConstants.TRUSTSTORE_FILE, >> new MemoryPasswordProvider(TestConstants.TRUSTSTORE_PWD), null, null); >> + final TrustStoreConfiguration ksc = new >> TrustStoreConfiguration(TestConstants.TRUSTSTORE_FILE, >> new MemoryPasswordProvider(TestConstants.TRUSTSTORE_PWD()), null, null); >> final KeyStore ks = ksc.getKeyStore(); >> final KeyStore ks2 = ksc.getKeyStore(); >> Assert.assertTrue(ks == ks2); >> >> http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/ >> 08077cba/src/changes/changes.xml >> ---------------------------------------------------------------------- >> diff --git a/src/changes/changes.xml b/src/changes/changes.xml >> index 55b18f9..94b1033 100644 >> --- a/src/changes/changes.xml >> +++ b/src/changes/changes.xml >> @@ -31,6 +31,9 @@ >> - "remove" - Removed >> --> >> <release version="2.9.2" date="2017-XX-XX" description="GA Release >> 2.9.2"> >> + <action issue="LOG4J2-2054" dev="rpopma" type="add"> >> + Provide ways to configure SSL that avoid plain-text passwords in >> the log4j configuration. The configuration may now specify a system >> environment variable that holds the password, or the path to a file that >> holds the password. >> + </action> >> <action issue="LOG4J2-2057" dev="rgoers" type="update"> >> Support new SLF4J binding mechanism introduced in SLF4J 1.8. >> </action> >> >> http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/ >> 08077cba/src/site/site.xml >> ---------------------------------------------------------------------- >> diff --git a/src/site/site.xml b/src/site/site.xml >> index dca832a..6de65be 100644 >> --- a/src/site/site.xml >> +++ b/src/site/site.xml >> @@ -147,6 +147,7 @@ >> <item name="SMTP" href="/manual/appenders.html#SMTPAppender"/> >> <item name="ScriptAppenderSelector" href="/manual/appenders.html# >> ScriptAppenderSelector"/> >> <item name="Socket" href="/manual/appenders.html# >> SocketAppender"/> >> + <item name="SSL" href="/manual/appenders.html#SSL"/> >> <item name="Syslog" href="/manual/appenders.html# >> SyslogAppender"/> >> <item name="ZeroMQ/JeroMQ" href="/manual/appenders.html# >> JeroMQAppender"/> >> </item> >> >> http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/ >> 08077cba/src/site/xdoc/manual/appenders.xml >> ---------------------------------------------------------------------- >> diff --git a/src/site/xdoc/manual/appenders.xml b/src/site/xdoc/manual/ >> appenders.xml >> index c4982c0..b9ef28a 100644 >> --- a/src/site/xdoc/manual/appenders.xml >> +++ b/src/site/xdoc/manual/appenders.xml >> @@ -1658,7 +1658,7 @@ public class JpaLogEntity extends >> AbstractLogEventWrapperEntity { >> <td>Ssl</td> >> <td>SslConfiguration</td> >> <td>Contains the configuration for the KeyStore and >> TrustStore for https. >> - Optional, uses Java runtime defaults if not >> specified.</td> >> + Optional, uses Java runtime defaults if not specified. >> See <a href="#SSL">SSL</a></td> >> </tr> >> <tr> >> <td>verifyHostname</td> >> @@ -1710,8 +1710,8 @@ public class JpaLogEntity extends >> AbstractLogEventWrapperEntity { >> <Property name="X-Java-Runtime" value="$${java:runtime}" /> >> <JsonLayout properties="true"/> >> <SSL> >> - <KeyStore location="log4j2-keystore.jks" password="changeme"/> >> - <TrustStore location="truststore.jks" password="changeme"/> >> + <KeyStore location="log4j2-keystore.jks" >> passwordEnvironmentVariable="KEYSTORE_PASSWORD"/> >> + <TrustStore location="truststore.jks" >> passwordFile="${sys:user.home}/truststore.pwd"/> >> </SSL> >> </Http> >> </Appenders>]]></pre> >> @@ -4355,7 +4355,7 @@ public class JpaLogEntity extends >> AbstractLogEventWrapperEntity { >> <p> >> The <code>SocketAppender</code> is an OutputStreamAppender >> that writes its output to a remote destination >> specified by a host and port. The data can be sent over >> either TCP or UDP and can be sent in any format. >> - You can optionally secure communication with SSL. >> + You can optionally secure communication with <a >> href="#SSL">SSL</a>. >> </p> >> <table> >> <caption align="top"><code>SocketAppender</code> >> Parameters</caption> >> @@ -4387,7 +4387,7 @@ public class JpaLogEntity extends >> AbstractLogEventWrapperEntity { >> <tr> >> <td>SSL</td> >> <td>SslConfiguration</td> >> - <td>Contains the configuration for the KeyStore and >> TrustStore.</td> >> + <td>Contains the configuration for the KeyStore and >> TrustStore. See <a href="#SSL">SSL</a>.</td> >> </tr> >> <tr> >> <td>filter</td> >> @@ -4467,7 +4467,7 @@ public class JpaLogEntity extends >> AbstractLogEventWrapperEntity { >> </Configuration>]]></pre> >> >> <p> >> - This is a secured SSL configuration: >> + This is a secured <a href="#SSL">SSL</a> configuration: >> </p> >> <pre class="prettyprint linenums"><![CDATA[<?xml version="1.0" >> encoding="UTF-8"?> >> <Configuration status="warn" name="MyApp" packages=""> >> @@ -4475,8 +4475,8 @@ public class JpaLogEntity extends >> AbstractLogEventWrapperEntity { >> <Socket name="socket" host="localhost" port="9500"> >> <JsonLayout properties="true"/> >> <SSL> >> - <KeyStore location="log4j2-keystore.jks" password="changeme"/> >> - <TrustStore location="truststore.jks" password="changeme"/> >> + <KeyStore location="log4j2-keystore.jks" >> passwordEnvironmentVariable="KEYSTORE_PASSWORD"/> >> + <TrustStore location="truststore.jks" >> passwordFile="${sys:user.home}/truststore.pwd"/> >> </SSL> >> </Socket> >> </Appenders> >> @@ -4488,6 +4488,154 @@ public class JpaLogEntity extends >> AbstractLogEventWrapperEntity { >> </Configuration>]]></pre> >> >> </subsection> >> + <a name="SSL" /> >> + <subsection name="SSL Configuration"> >> + <p> >> + Several appenders can be configured to use either a plain >> network connection or a Secure Socket Layer (SSL) >> + connection. This section documents the parameters available >> for SSL configuration. >> + </p> >> + <table> >> + <caption align="top">SSL Configuration Parameters</caption> >> + <tr> >> + <th>Parameter Name</th> >> + <th>Type</th> >> + <th>Description</th> >> + </tr> >> + <tr> >> + <td>protocol</td> >> + <td>String</td> >> + <td><code>SSL</code> if omitted. >> + See also <a href="http://docs.oracle.com/ >> javase/7/docs/technotes/guides/security/StandardNames.html#SSLContext">Standard >> names</a>.</td> >> + </tr> >> + <tr> >> + <td>KeyStore</td> >> + <td>KeyStore</td> >> + <td>Contains your private keys and certificates, >> + and determines which authentication credentials to send to >> the remote host.</td> >> + </tr> >> + <tr> >> + <td>TrustStore</td> >> + <td>TrustStore</td> >> + <td>Contains the CA certificates of the remote counterparty. >> + Determines whether the remote authentication credentials >> + (and thus the connection) should be trusted.</td> >> + </tr> >> + </table> >> + >> + <h4>KeyStore</h4> >> + The keystore is meant to contain your private keys and >> certificates, >> + and determines which authentication credentials to send to the >> remote host. >> + >> + <table> >> + <caption align="top">KeyStore Configuration >> Parameters</caption> >> + <tr> >> + <th>Parameter Name</th> >> + <th>Type</th> >> + <th>Description</th> >> + </tr> >> + <tr> >> + <td>location</td> >> + <td>String</td> >> + <td>Path to the keystore file.</td> >> + </tr> >> + <tr> >> + <td>password</td> >> + <td>char[]</td> >> + <td>Plain text password to access the keystore. Cannot be >> combined with either >> + <code>passwordEnvironmentVariable</code> or >> <code>passwordFile</code>.</td> >> + </tr> >> + <tr> >> + <td>passwordEnvironmentVariable</td> >> + <td>String</td> >> + <td>Name of an environment variable that holds the >> password. Cannot be combined with either >> + <code>password</code> or <code>passwordFile</code>.</td> >> + </tr> >> + <tr> >> + <td>passwordFile</td> >> + <td>String</td> >> + <td>Path to a file that holds the password. Cannot be >> combined with either >> + <code>password</code> or <code> >> passwordEnvironmentVariable</code>.</td> >> + </tr> >> + <tr> >> + <td>type</td> >> + <td>String</td> >> + <td>Optional KeyStore type, e.g. <code>JKS</code>, >> <code>PKCS12</code>, <code>PKCS11</code>, >> + <code>BKS</code>, <code>Windows-MY/Windows-ROOT</code>, >> <code>KeychainStore</code>, etc. >> + The default is JKS. See also <a href=" >> http://docs.oracle.com/javase/7/docs/technotes/ >> guides/security/StandardNames.html#KeyStore">Standard types</a>.</td> >> + </tr> >> + <tr> >> + <td>keyManagerFactoryAlgorithm</td> >> + <td>String</td> >> + <td>Optional KeyManagerFactory algorithm. The default is >> <code>SunX509</code>. >> + See also <a href="http://docs.oracle.com/ >> javase/7/docs/technotes/guides/security/StandardNames. >> html#KeyManagerFactory">Standard algorithms</a>.</td> >> + </tr> >> + </table> >> + >> + <h4>TrustStore</h4> >> + <p> >> + The trust store is meant to contain the CA certificates you >> are willing to trust >> + when a remote party presents its certificate. Determines >> whether the remote authentication credentials >> + (and thus the connection) should be trusted. >> + </p><p> >> + In some cases, they can be one and the same store, >> + although it is often better practice to use distinct stores >> (especially when they are file-based). >> + </p> >> + >> + <table> >> + <caption align="top">TrustStore Configuration >> Parameters</caption> >> + <tr> >> + <th>Parameter Name</th> >> + <th>Type</th> >> + <th>Description</th> >> + </tr> >> + <tr> >> + <td>location</td> >> + <td>String</td> >> + <td>Path to the keystore file.</td> >> + </tr> >> + <tr> >> + <td>password</td> >> + <td>char[]</td> >> + <td>Plain text password to access the keystore. Cannot be >> combined with either >> + <code>passwordEnvironmentVariable</code> or >> <code>passwordFile</code>.</td> >> + </tr> >> + <tr> >> + <td>passwordEnvironmentVariable</td> >> + <td>String</td> >> + <td>Name of an environment variable that holds the >> password. Cannot be combined with either >> + <code>password</code> or <code>passwordFile</code>.</td> >> + </tr> >> + <tr> >> + <td>passwordFile</td> >> + <td>String</td> >> + <td>Path to a file that holds the password. Cannot be >> combined with either >> + <code>password</code> or <code> >> passwordEnvironmentVariable</code>.</td> >> + </tr> >> + <tr> >> + <td>type</td> >> + <td>String</td> >> + <td>Optional KeyStore type, e.g. <code>JKS</code>, >> <code>PKCS12</code>, <code>PKCS11</code>, >> + <code>BKS</code>, <code>Windows-MY/Windows-ROOT</code>, >> <code>KeychainStore</code>, etc. >> + The default is JKS. See also <a href=" >> http://docs.oracle.com/javase/7/docs/technotes/ >> guides/security/StandardNames.html#KeyStore">Standard types</a>.</td> >> + </tr> >> + <tr> >> + <td>trustManagerFactoryAlgorithm</td> >> + <td>String</td> >> + <td>Optional TrustManagerFactory algorithm. The default is >> <code>SunX509</code>. >> + See also <a href="http://docs.oracle.com/ >> javase/7/docs/technotes/guides/security/StandardNames. >> html#TrustManagerFactory">Standard algorithms</a>.</td> >> + </tr> >> + </table> >> + >> + <h4>Example</h4> >> + <pre class="prettyprint linenums"><![CDATA[ >> + ... >> + <SSL> >> + <KeyStore location="log4j2-keystore.jks" >> passwordEnvironmentVariable="KEYSTORE_PASSWORD"/> >> + <TrustStore location="truststore.jks" >> passwordFile="${sys:user.home}/truststore.pwd"/> >> + </SSL> >> + ...]]></pre> >> + >> + </subsection> >> <a name="SyslogAppender"/> >> <subsection name="SyslogAppender"> >> <p> >> @@ -4659,7 +4807,7 @@ public class JpaLogEntity extends >> AbstractLogEventWrapperEntity { >> <tr> >> <td>SSL</td> >> <td>SslConfiguration</td> >> - <td>Contains the configuration for the KeyStore and >> TrustStore.</td> >> + <td>Contains the configuration for the KeyStore and >> TrustStore. See <a href="#SSL">SSL</a>.</td> >> </tr> >> <tr> >> <td>reconnectionDelayMillis</td> >> @@ -4695,7 +4843,7 @@ public class JpaLogEntity extends >> AbstractLogEventWrapperEntity { >> </Configuration>]]></pre> >> >> <p> >> - For SSL this appender writes its output to a remote >> destination specified by a host and port over SSL in >> + For <a href="#SSL">SSL</a> this appender writes its output to >> a remote destination specified by a host and port over SSL in >> a format that conforms with either the BSD Syslog format or >> the RFC 5424 format. >> </p> >> >> @@ -4704,8 +4852,8 @@ public class JpaLogEntity extends >> AbstractLogEventWrapperEntity { >> <Appenders> >> <TLSSyslog name="bsd" host="localhost" port="6514"> >> <SSL> >> - <KeyStore location="log4j2-keystore.jks" password="changeme"/> >> - <TrustStore location="truststore.jks" password="changeme"/> >> + <KeyStore location="log4j2-keystore.jks" >> passwordEnvironmentVariable="KEYSTORE_PASSWORD"/> >> + <TrustStore location="truststore.jks" >> passwordFile="${sys:user.home}/truststore.pwd"/> >> </SSL> >> </TLSSyslog> >> </Appenders> >> >>
