You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@logging.apache.org by Gary Gregory <ga...@gmail.com> on 2017/09/25 16:08:06 UTC
Re: logging-log4j2 git commit: 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
On Mon, Sep 25, 2017 at 10:00 AM, <rp...@apache.org> 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 <rp...@apache.org>
> Authored: Tue Sep 26 01:00:15 2017 +0900
> Committer: rpopma <rp...@apache.org>
> 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>
>
>
Re: logging-log4j2 git commit: 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
Posted by Remko Popma <re...@gmail.com>.
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 <ga...@gmail.com> wrote:
>
>> On Mon, Sep 25, 2017 at 10:00 AM, <rp...@apache.org> 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 <rp...@apache.org>
>> Authored: Tue Sep 26 01:00:15 2017 +0900
>> Committer: rpopma <rp...@apache.org>
>> 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>
>>
>>