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

Reply via email to