ARTEMIS-1600 Support masked passwords in bootstrap.xm and login.config

We provide a feature to mask passwords in the configuration files.
However, passwords in the bootstrap.xml (when the console is
secured with HTTPS) cannot be masked. This enhancement has
been opened to allow passwords in the bootstrap.xml to be masked
using the built-in masking feature provided by the broker.

Also the LDAPLoginModule configuration (in login.config) has a
connection password attribute that also needs this mask support.

In addition the ENC() syntax is supported for password masking
to replace the old 'mask-password' flag.


Project: http://git-wip-us.apache.org/repos/asf/activemq-artemis/repo
Commit: http://git-wip-us.apache.org/repos/asf/activemq-artemis/commit/bb84f679
Tree: http://git-wip-us.apache.org/repos/asf/activemq-artemis/tree/bb84f679
Diff: http://git-wip-us.apache.org/repos/asf/activemq-artemis/diff/bb84f679

Branch: refs/heads/master
Commit: bb84f679363f62e8b2663f63bf23f04133de481d
Parents: 1d31227
Author: Howard Gao <howard....@gmail.com>
Authored: Thu Jan 18 14:31:32 2018 +0800
Committer: Justin Bertram <jbert...@apache.org>
Committed: Thu Jan 18 08:59:00 2018 -0600

----------------------------------------------------------------------
 .../apache/activemq/cli/test/HashUtilTest.java  |  47 ++++++
 .../artemis/utils/PasswordMaskingUtil.java      |  48 +++++-
 .../artemis/utils/SecureHashProcessor.java      |   7 +-
 .../artemis/utils/SensitiveDataCodec.java       |   3 +-
 .../utils/MaskPasswordResolvingTest.java        | 116 ++++++++++++++
 .../config/ActiveMQDefaultConfiguration.java    |   4 +-
 .../client/ActiveMQClientMessageBundle.java     |   6 -
 .../artemis/utils/ConfigurationHelper.java      |  19 +--
 artemis-dto/pom.xml                             |   8 +
 .../activemq/artemis/dto/WebServerDTO.java      |  35 ++++-
 .../artemis/jms/bridge/impl/JMSBridgeImpl.java  |  27 +---
 .../artemis/ra/ActiveMQRAProperties.java        |  28 +---
 .../artemis/ra/ActiveMQResourceAdapter.java     |   5 +-
 .../artemis/ra/inflow/ActiveMQActivation.java   |  18 +--
 .../artemis/core/config/Configuration.java      |   4 +-
 .../core/config/impl/ConfigurationImpl.java     |  23 ++-
 .../config/impl/FileSecurityConfiguration.java  |  16 +-
 .../deployers/impl/FileConfigurationParser.java |  37 ++---
 .../spi/core/security/jaas/LDAPLoginModule.java |  37 ++++-
 .../artemis/utils/XMLConfigurationUtil.java     |   2 +-
 .../impl/FileConfigurationParserTest.java       |  82 ++++++++++
 .../jaas/LDAPLoginModuleMaskPasswordTest.java   | 156 +++++++++++++++++++
 .../jaas/PropertiesLoginModuleTest.java         |   7 +
 artemis-server/src/test/resources/login.config  |  59 +++++++
 .../src/test/resources/users.properties         |   1 +
 artemis-web/pom.xml                             |   7 +
 .../artemis/component/WebServerComponent.java   |   4 +-
 .../cli/test/WebServerComponentTest.java        |  51 +++++-
 .../src/test/resources/bootstrap_secure_web.xml |  34 ++++
 .../src/test/resources/bootstrap_web.xml        |  34 ++++
 .../src/test/resources/bootstrap_web_codec.xml  |  34 ++++
 docs/user-manual/en/masking-passwords.md        | 141 +++++++++++++++--
 .../integration/ra/ResourceAdapterTest.java     |  84 +++++++++-
 .../jms/bridge/impl/JMSBridgeImplTest.java      |  39 +++++
 34 files changed, 1057 insertions(+), 166 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/bb84f679/artemis-cli/src/test/java/org/apache/activemq/cli/test/HashUtilTest.java
----------------------------------------------------------------------
diff --git 
a/artemis-cli/src/test/java/org/apache/activemq/cli/test/HashUtilTest.java 
b/artemis-cli/src/test/java/org/apache/activemq/cli/test/HashUtilTest.java
new file mode 100644
index 0000000..09a5208
--- /dev/null
+++ b/artemis-cli/src/test/java/org/apache/activemq/cli/test/HashUtilTest.java
@@ -0,0 +1,47 @@
+/*
+ * 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.activemq.cli.test;
+
+import org.apache.activemq.artemis.cli.commands.util.HashUtil;
+import org.apache.activemq.artemis.utils.PasswordMaskingUtil;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+public class HashUtilTest {
+
+   @Test
+   public void testDefaultHashFormat() throws Exception {
+      final String password = "helloworld";
+      String hash = HashUtil.tryHash(new TestActionContext(), password);
+      String hashStr = PasswordMaskingUtil.unwrap(hash);
+      System.out.println("hashString: " + hashStr);
+      String[] parts = hashStr.split(":");
+      assertEquals(3, parts.length);
+      //first part should be able to convert to an int
+      Integer.parseInt(parts[0]);
+      //second and third parts are all hex values
+      checkHexBytes(parts[1], parts[2]);
+   }
+
+   private void checkHexBytes(String... parts) throws Exception {
+      for (String p : parts) {
+         assertTrue(p.matches("^[0-9A-F]+$"));
+      }
+   }
+}

http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/bb84f679/artemis-commons/src/main/java/org/apache/activemq/artemis/utils/PasswordMaskingUtil.java
----------------------------------------------------------------------
diff --git 
a/artemis-commons/src/main/java/org/apache/activemq/artemis/utils/PasswordMaskingUtil.java
 
b/artemis-commons/src/main/java/org/apache/activemq/artemis/utils/PasswordMaskingUtil.java
index dbc20c5..be56046 100644
--- 
a/artemis-commons/src/main/java/org/apache/activemq/artemis/utils/PasswordMaskingUtil.java
+++ 
b/artemis-commons/src/main/java/org/apache/activemq/artemis/utils/PasswordMaskingUtil.java
@@ -28,14 +28,54 @@ import org.apache.activemq.artemis.logs.ActiveMQUtilBundle;
 
 public final class PasswordMaskingUtil {
 
+   public static final String BEGIN_ENC = "ENC(";
+   public static final String END_ENC = ")";
+
    private PasswordMaskingUtil() {
 
    }
 
+   /**
+    * This method deals with password masking and returns the password in its 
plain text form.
+    * @param maskPassword : explicit mask flag. If it's true, the password is 
interpreted as
+    *                     masked. If it is false, the password is interpreted 
as plain text.
+    *                     if it is null, the password will be interpreted as 
masked if the
+    *                     password is wrapped in ENC(), or as plain text 
otherwise.
+    * @param password : the original value of password string
+    * @param codecClass : the codec used to decode the password. Only when the 
password is interpreted
+    *              as masked will this codec be used. Ignored otherwise.
+    * @return
+    */
+   public static String resolveMask(Boolean maskPassword, String password, 
String codecClass) throws Exception {
+      String plainText = password;
+      if (maskPassword == null) {
+         if (isEncMasked(password)) {
+            //masked
+            String bareMaskedPassword = unwrap(password);
+            plainText = getCodec(codecClass).decode(bareMaskedPassword);
+         }
+      } else if (maskPassword) {
+         plainText = getCodec(codecClass).decode(password);
+      }
+      return plainText;
+   }
+
+   public static boolean isEncMasked(String password) {
+      return (password.startsWith(BEGIN_ENC) && password.endsWith(END_ENC));
+   }
+
+   //remove ENC() from the password body
+   public static String unwrap(String password) {
+      return password.substring(4, password.length() - 1);
+   }
+
+   public static String wrap(String password) {
+      return BEGIN_ENC + password + END_ENC;
+   }
+
    private static final class LazyPlainTextProcessorHolder {
 
       private LazyPlainTextProcessorHolder() {
-
       }
 
       private static final HashProcessor INSTANCE = new NoHashProcessor();
@@ -83,7 +123,7 @@ public final class PasswordMaskingUtil {
    }
 
    private static boolean isEncoded(String storedPassword) {
-      return storedPassword == null || 
(storedPassword.startsWith(SecureHashProcessor.BEGIN_HASH) && 
storedPassword.endsWith(SecureHashProcessor.END_HASH));
+      return storedPassword == null || (isEncMasked(storedPassword));
    }
 
    public static HashProcessor getHashProcessor() {
@@ -107,6 +147,10 @@ public final class PasswordMaskingUtil {
    public static SensitiveDataCodec<String> getCodec(String codecDesc) throws 
ActiveMQException {
       SensitiveDataCodec<String> codecInstance;
 
+      if (codecDesc == null) {
+         return getDefaultCodec();
+      }
+
       // semi colons
       String[] parts = codecDesc.split(";");
       if (parts.length < 1)

http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/bb84f679/artemis-commons/src/main/java/org/apache/activemq/artemis/utils/SecureHashProcessor.java
----------------------------------------------------------------------
diff --git 
a/artemis-commons/src/main/java/org/apache/activemq/artemis/utils/SecureHashProcessor.java
 
b/artemis-commons/src/main/java/org/apache/activemq/artemis/utils/SecureHashProcessor.java
index 8e9cd5c..a17cfd4 100644
--- 
a/artemis-commons/src/main/java/org/apache/activemq/artemis/utils/SecureHashProcessor.java
+++ 
b/artemis-commons/src/main/java/org/apache/activemq/artemis/utils/SecureHashProcessor.java
@@ -18,9 +18,6 @@ package org.apache.activemq.artemis.utils;
 
 public class SecureHashProcessor implements HashProcessor {
 
-   public static final String BEGIN_HASH = "ENC(";
-   public static final String END_HASH = ")";
-
    private DefaultSensitiveStringCodec codec;
 
    public SecureHashProcessor(DefaultSensitiveStringCodec codec) {
@@ -29,13 +26,13 @@ public class SecureHashProcessor implements HashProcessor {
 
    @Override
    public String hash(String plainText) throws Exception {
-      return BEGIN_HASH + codec.encode(plainText) + END_HASH;
+      return PasswordMaskingUtil.wrap(codec.encode(plainText));
    }
 
    @Override
    //storedValue must take form of ENC(...)
    public boolean compare(char[] inputValue, String storedValue) {
-      String storedHash = storedValue.substring(4, storedValue.length() - 2);
+      String storedHash = storedValue.substring(4, storedValue.length() - 1);
       return codec.verify(inputValue, storedHash);
    }
 }

http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/bb84f679/artemis-commons/src/main/java/org/apache/activemq/artemis/utils/SensitiveDataCodec.java
----------------------------------------------------------------------
diff --git 
a/artemis-commons/src/main/java/org/apache/activemq/artemis/utils/SensitiveDataCodec.java
 
b/artemis-commons/src/main/java/org/apache/activemq/artemis/utils/SensitiveDataCodec.java
index d585976..cbd17e5 100644
--- 
a/artemis-commons/src/main/java/org/apache/activemq/artemis/utils/SensitiveDataCodec.java
+++ 
b/artemis-commons/src/main/java/org/apache/activemq/artemis/utils/SensitiveDataCodec.java
@@ -31,5 +31,6 @@ public interface SensitiveDataCodec<T> {
 
    T encode(Object secret) throws Exception;
 
-   void init(Map<String, String> params) throws Exception;
+   default void init(Map<String, String> params) throws Exception {
+   };
 }

http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/bb84f679/artemis-commons/src/test/java/org/apache/activemq/artemis/utils/MaskPasswordResolvingTest.java
----------------------------------------------------------------------
diff --git 
a/artemis-commons/src/test/java/org/apache/activemq/artemis/utils/MaskPasswordResolvingTest.java
 
b/artemis-commons/src/test/java/org/apache/activemq/artemis/utils/MaskPasswordResolvingTest.java
new file mode 100644
index 0000000..5a99ccc
--- /dev/null
+++ 
b/artemis-commons/src/test/java/org/apache/activemq/artemis/utils/MaskPasswordResolvingTest.java
@@ -0,0 +1,116 @@
+/*
+ * 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.activemq.artemis.utils;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.junit.Assert.assertEquals;
+
+@RunWith(Parameterized.class)
+public class MaskPasswordResolvingTest {
+
+   private static final String plainPassword = "password";
+   private static final String defaultMaskPassword = "defaultmasked";
+   private static final String customizedCodecPassword = "secret";
+   private static final String oldDefaultMaskedPassword = "oldmasked";
+   private static final String oldCustomizedCodecPassword = "secret";
+   private static final String oldExplicitPlainPassword = "PASSWORD";
+
+   @Parameterized.Parameters(name = "mask({0})password({1})codec({2})")
+   public static Collection<Object[]> params() {
+      return Arrays.asList(new Object[][]{{null, plainPassword, null},
+                                          {null, 
"ENC(3bdfd94fe8cdf710e7fefa72f809ea90)", null},
+                                          {null, "ENC(momsword)", 
"org.apache.activemq.artemis.utils.MaskPasswordResolvingTest$SimplePasswordCodec"},
+                                          {true, 
"662d05f5a83f9e073af6b8dc081d34aa", null},
+                                          {true, "momsword", 
"org.apache.activemq.artemis.utils.MaskPasswordResolvingTest$SimplePasswordCodec"},
+                                          {false, oldExplicitPlainPassword, 
null},
+                                          {false, oldExplicitPlainPassword, 
"org.apache.activemq.artemis.utils.MaskPasswordResolvingTest$SimplePasswordCodec"}});
+   }
+
+   private Boolean maskPassword;
+   private String password;
+   private String codec;
+
+   public MaskPasswordResolvingTest(Boolean maskPassword, String password, 
String codec) {
+      this.maskPassword = maskPassword;
+      this.password = password;
+      this.codec = codec;
+   }
+
+   @Test
+   public void testPasswordResolving() throws Exception {
+      String resolved = PasswordMaskingUtil.resolveMask(maskPassword, 
password, codec);
+      System.out.println("resolved: " + resolved);
+      checkResult(resolved);
+   }
+
+   private void checkResult(String resolved) throws Exception {
+      if (this.maskPassword == null) {
+         if (PasswordMaskingUtil.isEncMasked(this.password)) {
+            if (this.codec != null) {
+               assertEquals(customizedCodecPassword, resolved);
+            } else {
+               assertEquals(defaultMaskPassword, resolved);
+            }
+         } else {
+            assertEquals(plainPassword, resolved);
+         }
+      } else {
+         if (this.maskPassword) {
+            if (this.codec != null) {
+               assertEquals(oldCustomizedCodecPassword, resolved);
+            } else {
+               assertEquals(oldDefaultMaskedPassword, resolved);
+            }
+         } else {
+            assertEquals(oldExplicitPlainPassword, resolved);
+         }
+      }
+   }
+
+   public static class SimplePasswordCodec implements 
SensitiveDataCodec<String> {
+
+      private Map<String, String> passwordBook = new HashMap<>();
+
+      public SimplePasswordCodec() {
+         passwordBook.put("momsword", "secret");
+         passwordBook.put("youneverknow", "keypass");
+         passwordBook.put("youcanguess", "trustpass");
+      }
+
+      @Override
+      public String decode(Object mask) throws Exception {
+         String password = passwordBook.get(mask);
+         if (password == null) {
+            throw new IllegalArgumentException("I don't know the password " + 
mask);
+         }
+         return password;
+      }
+
+      @Override
+      public String encode(Object secret) throws Exception {
+         return null;
+      }
+   }
+}

http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/bb84f679/artemis-core-client/src/main/java/org/apache/activemq/artemis/api/config/ActiveMQDefaultConfiguration.java
----------------------------------------------------------------------
diff --git 
a/artemis-core-client/src/main/java/org/apache/activemq/artemis/api/config/ActiveMQDefaultConfiguration.java
 
b/artemis-core-client/src/main/java/org/apache/activemq/artemis/api/config/ActiveMQDefaultConfiguration.java
index 9b5d75d..fecf71c 100644
--- 
a/artemis-core-client/src/main/java/org/apache/activemq/artemis/api/config/ActiveMQDefaultConfiguration.java
+++ 
b/artemis-core-client/src/main/java/org/apache/activemq/artemis/api/config/ActiveMQDefaultConfiguration.java
@@ -179,7 +179,7 @@ public final class ActiveMQDefaultConfiguration {
    private static String DEFAULT_CLUSTER_PASSWORD = "CHANGE ME!!";
 
    // This option controls whether passwords in server configuration need be 
masked. If set to "true" the passwords are masked.
-   private static boolean DEFAULT_MASK_PASSWORD = false;
+   private static Boolean DEFAULT_MASK_PASSWORD = null;
 
    // true means that the management API is available via JMX
    private static boolean DEFAULT_JMX_MANAGEMENT_ENABLED = true;
@@ -622,7 +622,7 @@ public final class ActiveMQDefaultConfiguration {
    /**
     * This option controls whether passwords in server configuration need be 
masked. If set to "true" the passwords are masked.
     */
-   public static boolean isDefaultMaskPassword() {
+   public static Boolean isDefaultMaskPassword() {
       return DEFAULT_MASK_PASSWORD;
    }
 

http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/bb84f679/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/client/ActiveMQClientMessageBundle.java
----------------------------------------------------------------------
diff --git 
a/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/client/ActiveMQClientMessageBundle.java
 
b/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/client/ActiveMQClientMessageBundle.java
index 64107b9..bb88e6d 100644
--- 
a/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/client/ActiveMQClientMessageBundle.java
+++ 
b/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/client/ActiveMQClientMessageBundle.java
@@ -178,9 +178,6 @@ public interface ActiveMQClientMessageBundle {
    @Message(id = 119043, value = "Invalid argument null handler")
    IllegalArgumentException nullHandler();
 
-   @Message(id = 119044, value = "No available codec to decode password!")
-   IllegalArgumentException noCodec();
-
    @Message(id = 119045, value = "the first node to be compared is null")
    IllegalArgumentException firstNodeNull();
 
@@ -214,9 +211,6 @@ public interface ActiveMQClientMessageBundle {
    @Message(id = 119055, value = "Element {0} requires a valid Long value, but 
''{1}'' cannot be parsed as a Long", format = Message.Format.MESSAGE_FORMAT)
    IllegalArgumentException mustBeLong(Node element, String value);
 
-   @Message(id = 119056, value = "Failed to get decoder")
-   IllegalArgumentException failedToGetDecoder(@Cause Exception e);
-
    @Message(id = 119057, value = "Error decoding password")
    IllegalArgumentException errordecodingPassword(@Cause Exception e);
 

http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/bb84f679/artemis-core-client/src/main/java/org/apache/activemq/artemis/utils/ConfigurationHelper.java
----------------------------------------------------------------------
diff --git 
a/artemis-core-client/src/main/java/org/apache/activemq/artemis/utils/ConfigurationHelper.java
 
b/artemis-core-client/src/main/java/org/apache/activemq/artemis/utils/ConfigurationHelper.java
index a205c19..4367318 100644
--- 
a/artemis-core-client/src/main/java/org/apache/activemq/artemis/utils/ConfigurationHelper.java
+++ 
b/artemis-core-client/src/main/java/org/apache/activemq/artemis/utils/ConfigurationHelper.java
@@ -20,7 +20,6 @@ import java.util.HashSet;
 import java.util.Map;
 import java.util.Set;
 
-import org.apache.activemq.artemis.api.core.ActiveMQException;
 import org.apache.activemq.artemis.core.client.ActiveMQClientLogger;
 import org.apache.activemq.artemis.core.client.ActiveMQClientMessageBundle;
 
@@ -164,25 +163,9 @@ public class ConfigurationHelper {
 
       String value = prop.toString();
       Boolean useMask = (Boolean) props.get(defaultMaskPassword);
-      if (useMask == null || (!useMask)) {
-         return value;
-      }
-
       final String classImpl = (String) props.get(defaultPasswordCodec);
-
-      if (classImpl == null) {
-         throw ActiveMQClientMessageBundle.BUNDLE.noCodec();
-      }
-
-      SensitiveDataCodec<String> codec = null;
-      try {
-         codec = PasswordMaskingUtil.getCodec(classImpl);
-      } catch (ActiveMQException e1) {
-         throw ActiveMQClientMessageBundle.BUNDLE.failedToGetDecoder(e1);
-      }
-
       try {
-         return codec.decode(value);
+         return PasswordMaskingUtil.resolveMask(useMask, value, classImpl);
       } catch (Exception e) {
          throw ActiveMQClientMessageBundle.BUNDLE.errordecodingPassword(e);
       }

http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/bb84f679/artemis-dto/pom.xml
----------------------------------------------------------------------
diff --git a/artemis-dto/pom.xml b/artemis-dto/pom.xml
index 05de601..f875957 100644
--- a/artemis-dto/pom.xml
+++ b/artemis-dto/pom.xml
@@ -31,6 +31,14 @@
       <activemq.basedir>${project.basedir}/..</activemq.basedir>
    </properties>
 
+   <dependencies>
+      <dependency>
+         <groupId>org.apache.activemq</groupId>
+         <artifactId>artemis-commons</artifactId>
+         <version>${project.version}</version>
+      </dependency>
+   </dependencies>
+
    <build>
       <resources>
          <resource>

http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/bb84f679/artemis-dto/src/main/java/org/apache/activemq/artemis/dto/WebServerDTO.java
----------------------------------------------------------------------
diff --git 
a/artemis-dto/src/main/java/org/apache/activemq/artemis/dto/WebServerDTO.java 
b/artemis-dto/src/main/java/org/apache/activemq/artemis/dto/WebServerDTO.java
index 4553e0a..3e15261 100644
--- 
a/artemis-dto/src/main/java/org/apache/activemq/artemis/dto/WebServerDTO.java
+++ 
b/artemis-dto/src/main/java/org/apache/activemq/artemis/dto/WebServerDTO.java
@@ -16,6 +16,8 @@
  */
 package org.apache.activemq.artemis.dto;
 
+import org.apache.activemq.artemis.utils.PasswordMaskingUtil;
+
 import javax.xml.bind.annotation.XmlAccessType;
 import javax.xml.bind.annotation.XmlAccessorType;
 import javax.xml.bind.annotation.XmlAttribute;
@@ -37,21 +39,44 @@ public class WebServerDTO extends ComponentDTO {
    public Boolean clientAuth;
 
    @XmlAttribute
-   public String keyStorePath;
+   public String passwordCodec;
 
    @XmlAttribute
-   public String keyStorePassword;
+   public String keyStorePath;
 
    @XmlAttribute
    public String trustStorePath;
 
-   @XmlAttribute
-   public String trustStorePassword;
-
    @XmlElementRef
    public List<AppDTO> apps;
 
+   @XmlAttribute
+   private String keyStorePassword;
+
+   @XmlAttribute
+   private String trustStorePassword;
+
    public WebServerDTO() {
       componentClassName = 
"org.apache.activemq.artemis.component.WebServerComponent";
    }
+
+   public String getKeyStorePassword() throws Exception {
+      return getPassword(this.keyStorePassword);
+   }
+
+   private String getPassword(String password) throws Exception {
+      return PasswordMaskingUtil.resolveMask(null, password, 
this.passwordCodec);
+   }
+
+   public void setKeyStorePassword(String keyStorePassword) {
+      this.keyStorePassword = keyStorePassword;
+   }
+
+   public String getTrustStorePassword() throws Exception {
+      return getPassword(this.trustStorePassword);
+   }
+
+   public void setTrustStorePassword(String trustStorePassword) {
+      this.trustStorePassword = trustStorePassword;
+   }
 }

http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/bb84f679/artemis-jms-server/src/main/java/org/apache/activemq/artemis/jms/bridge/impl/JMSBridgeImpl.java
----------------------------------------------------------------------
diff --git 
a/artemis-jms-server/src/main/java/org/apache/activemq/artemis/jms/bridge/impl/JMSBridgeImpl.java
 
b/artemis-jms-server/src/main/java/org/apache/activemq/artemis/jms/bridge/impl/JMSBridgeImpl.java
index b67b0b3..4d9b04e 100644
--- 
a/artemis-jms-server/src/main/java/org/apache/activemq/artemis/jms/bridge/impl/JMSBridgeImpl.java
+++ 
b/artemis-jms-server/src/main/java/org/apache/activemq/artemis/jms/bridge/impl/JMSBridgeImpl.java
@@ -69,9 +69,7 @@ import 
org.apache.activemq.artemis.jms.server.ActiveMQJMSServerBundle;
 import org.apache.activemq.artemis.service.extensions.ServiceUtils;
 import 
org.apache.activemq.artemis.service.extensions.xa.recovery.ActiveMQRegistry;
 import 
org.apache.activemq.artemis.service.extensions.xa.recovery.XARecoveryConfig;
-import org.apache.activemq.artemis.utils.DefaultSensitiveStringCodec;
 import org.apache.activemq.artemis.utils.PasswordMaskingUtil;
-import org.apache.activemq.artemis.utils.SensitiveDataCodec;
 
 public final class JMSBridgeImpl implements JMSBridge {
 
@@ -168,7 +166,7 @@ public final class JMSBridgeImpl implements JMSBridge {
 
    private ObjectName objectName;
 
-   private boolean useMaskedPassword = false;
+   private Boolean useMaskedPassword;
 
    private String passwordCodec;
 
@@ -440,25 +438,16 @@ public final class JMSBridgeImpl implements JMSBridge {
    }
 
    private void initPasswords() throws ActiveMQException {
-      if (useMaskedPassword) {
-         SensitiveDataCodec<String> codecInstance = new 
DefaultSensitiveStringCodec();
-
-         if (passwordCodec != null) {
-            codecInstance = PasswordMaskingUtil.getCodec(passwordCodec);
+      try {
+         if (this.sourcePassword != null) {
+            sourcePassword = 
PasswordMaskingUtil.resolveMask(useMaskedPassword, sourcePassword, 
passwordCodec);
          }
 
-         try {
-            if (this.sourcePassword != null) {
-               sourcePassword = codecInstance.decode(sourcePassword);
-            }
-
-            if (this.targetPassword != null) {
-               targetPassword = codecInstance.decode(targetPassword);
-            }
-         } catch (Exception e) {
-            throw ActiveMQJMSServerBundle.BUNDLE.errorDecodingPassword(e);
+         if (this.targetPassword != null) {
+            targetPassword = 
PasswordMaskingUtil.resolveMask(useMaskedPassword, targetPassword, 
passwordCodec);
          }
-
+      } catch (Exception e) {
+         throw ActiveMQJMSServerBundle.BUNDLE.errorDecodingPassword(e);
       }
    }
 

http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/bb84f679/artemis-ra/src/main/java/org/apache/activemq/artemis/ra/ActiveMQRAProperties.java
----------------------------------------------------------------------
diff --git 
a/artemis-ra/src/main/java/org/apache/activemq/artemis/ra/ActiveMQRAProperties.java
 
b/artemis-ra/src/main/java/org/apache/activemq/artemis/ra/ActiveMQRAProperties.java
index dffd5b3..e56e80d 100644
--- 
a/artemis-ra/src/main/java/org/apache/activemq/artemis/ra/ActiveMQRAProperties.java
+++ 
b/artemis-ra/src/main/java/org/apache/activemq/artemis/ra/ActiveMQRAProperties.java
@@ -20,9 +20,7 @@ import java.io.Serializable;
 import java.util.Hashtable;
 
 import org.apache.activemq.artemis.api.core.ActiveMQException;
-import org.apache.activemq.artemis.utils.DefaultSensitiveStringCodec;
 import org.apache.activemq.artemis.utils.PasswordMaskingUtil;
-import org.apache.activemq.artemis.utils.SensitiveDataCodec;
 
 /**
  * The RA default properties - these are set in the ra.xml file
@@ -66,14 +64,12 @@ public class ActiveMQRAProperties extends 
ConnectionFactoryProperties implements
 
    private boolean useJNDI;
 
-   private boolean useMaskedPassword = false;
+   private Boolean useMaskedPassword = null;
 
    private String passwordCodec;
 
    private boolean initialized = false;
 
-   private transient SensitiveDataCodec<String> codecInstance;
-
    /**
     * Class used to get a JChannel
     */
@@ -217,11 +213,11 @@ public class ActiveMQRAProperties extends 
ConnectionFactoryProperties implements
       this.setupInterval = setupInterval;
    }
 
-   public boolean isUseMaskedPassword() {
+   public Boolean isUseMaskedPassword() {
       return useMaskedPassword;
    }
 
-   public void setUseMaskedPassword(boolean useMaskedPassword) {
+   public void setUseMaskedPassword(Boolean useMaskedPassword) {
       this.useMaskedPassword = useMaskedPassword;
    }
 
@@ -243,27 +239,19 @@ public class ActiveMQRAProperties extends 
ConnectionFactoryProperties implements
       if (initialized)
          return;
 
-      if (useMaskedPassword) {
-         codecInstance = new DefaultSensitiveStringCodec();
-
-         if (passwordCodec != null) {
-            codecInstance = PasswordMaskingUtil.getCodec(passwordCodec);
-         }
-
+      if (password != null) {
          try {
-            if (password != null) {
-               password = codecInstance.decode(password);
-            }
+            password = PasswordMaskingUtil.resolveMask(useMaskedPassword, 
password, passwordCodec);
          } catch (Exception e) {
             throw ActiveMQRABundle.BUNDLE.errorDecodingPassword(e);
          }
-
       }
+
       initialized = true;
    }
 
-   public SensitiveDataCodec<String> getCodecInstance() {
-      return codecInstance;
+   public String getCodec() {
+      return passwordCodec;
    }
 
    public String getJgroupsChannelLocatorClass() {

http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/bb84f679/artemis-ra/src/main/java/org/apache/activemq/artemis/ra/ActiveMQResourceAdapter.java
----------------------------------------------------------------------
diff --git 
a/artemis-ra/src/main/java/org/apache/activemq/artemis/ra/ActiveMQResourceAdapter.java
 
b/artemis-ra/src/main/java/org/apache/activemq/artemis/ra/ActiveMQResourceAdapter.java
index a43d37b..684792e 100644
--- 
a/artemis-ra/src/main/java/org/apache/activemq/artemis/ra/ActiveMQResourceAdapter.java
+++ 
b/artemis-ra/src/main/java/org/apache/activemq/artemis/ra/ActiveMQResourceAdapter.java
@@ -59,7 +59,6 @@ import 
org.apache.activemq.artemis.ra.inflow.ActiveMQActivationSpec;
 import org.apache.activemq.artemis.ra.recovery.RecoveryManager;
 import org.apache.activemq.artemis.service.extensions.ServiceUtils;
 import 
org.apache.activemq.artemis.service.extensions.xa.recovery.XARecoveryConfig;
-import org.apache.activemq.artemis.utils.SensitiveDataCodec;
 import org.jboss.logging.Logger;
 import org.jgroups.JChannel;
 
@@ -2037,8 +2036,8 @@ public class ActiveMQResourceAdapter implements 
ResourceAdapter, Serializable {
       managedConnectionFactories.add(activeMQRAManagedConnectionFactory);
    }
 
-   public SensitiveDataCodec<String> getCodecInstance() {
-      return raProperties.getCodecInstance();
+   public String getCodec() {
+      return raProperties.getCodec();
    }
 
    public synchronized void closeConnectionFactory(ConnectionFactoryProperties 
properties) {

http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/bb84f679/artemis-ra/src/main/java/org/apache/activemq/artemis/ra/inflow/ActiveMQActivation.java
----------------------------------------------------------------------
diff --git 
a/artemis-ra/src/main/java/org/apache/activemq/artemis/ra/inflow/ActiveMQActivation.java
 
b/artemis-ra/src/main/java/org/apache/activemq/artemis/ra/inflow/ActiveMQActivation.java
index dc4d648..97498a2 100644
--- 
a/artemis-ra/src/main/java/org/apache/activemq/artemis/ra/inflow/ActiveMQActivation.java
+++ 
b/artemis-ra/src/main/java/org/apache/activemq/artemis/ra/inflow/ActiveMQActivation.java
@@ -57,7 +57,7 @@ import org.apache.activemq.artemis.ra.ActiveMQRaUtils;
 import org.apache.activemq.artemis.ra.ActiveMQResourceAdapter;
 import 
org.apache.activemq.artemis.service.extensions.xa.recovery.XARecoveryConfig;
 import org.apache.activemq.artemis.utils.FutureLatch;
-import org.apache.activemq.artemis.utils.SensitiveDataCodec;
+import org.apache.activemq.artemis.utils.PasswordMaskingUtil;
 import org.jboss.logging.Logger;
 
 /**
@@ -148,16 +148,12 @@ public class ActiveMQActivation {
          logger.trace("constructor(" + ra + ", " + endpointFactory + ", " + 
spec + ")");
       }
 
-      if (ra.isUseMaskedPassword()) {
-         String pass = spec.getOwnPassword();
-         if (pass != null) {
-            SensitiveDataCodec<String> codec = ra.getCodecInstance();
-
-            try {
-               spec.setPassword(codec.decode(pass));
-            } catch (Exception e) {
-               throw new ResourceException(e);
-            }
+      String pass = spec.getOwnPassword();
+      if (pass != null) {
+         try {
+            
spec.setPassword(PasswordMaskingUtil.resolveMask(ra.isUseMaskedPassword(), 
pass, ra.getCodec()));
+         } catch (Exception e) {
+            throw new ResourceException(e);
          }
       }
 

http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/bb84f679/artemis-server/src/main/java/org/apache/activemq/artemis/core/config/Configuration.java
----------------------------------------------------------------------
diff --git 
a/artemis-server/src/main/java/org/apache/activemq/artemis/core/config/Configuration.java
 
b/artemis-server/src/main/java/org/apache/activemq/artemis/core/config/Configuration.java
index 6f44bbb..f052248 100644
--- 
a/artemis-server/src/main/java/org/apache/activemq/artemis/core/config/Configuration.java
+++ 
b/artemis-server/src/main/java/org/apache/activemq/artemis/core/config/Configuration.java
@@ -1000,12 +1000,12 @@ public interface Configuration {
    /**
     * Sets if passwords should be masked or not. True means the passwords 
should be masked.
     */
-   Configuration setMaskPassword(boolean maskPassword);
+   Configuration setMaskPassword(Boolean maskPassword);
 
    /**
     * If passwords are masked. True means the passwords are masked.
     */
-   boolean isMaskPassword();
+   Boolean isMaskPassword();
 
    /*
    * Whether or not that ActiveMQ Artemis should use all protocols available 
on the classpath. If false only the core protocol will

http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/bb84f679/artemis-server/src/main/java/org/apache/activemq/artemis/core/config/impl/ConfigurationImpl.java
----------------------------------------------------------------------
diff --git 
a/artemis-server/src/main/java/org/apache/activemq/artemis/core/config/impl/ConfigurationImpl.java
 
b/artemis-server/src/main/java/org/apache/activemq/artemis/core/config/impl/ConfigurationImpl.java
index ff68f15..93085f9 100644
--- 
a/artemis-server/src/main/java/org/apache/activemq/artemis/core/config/impl/ConfigurationImpl.java
+++ 
b/artemis-server/src/main/java/org/apache/activemq/artemis/core/config/impl/ConfigurationImpl.java
@@ -249,7 +249,7 @@ public class ConfigurationImpl implements Configuration, 
Serializable {
 
    protected List<ConnectorServiceConfiguration> 
connectorServiceConfigurations = new ArrayList<>();
 
-   private boolean maskPassword = 
ActiveMQDefaultConfiguration.isDefaultMaskPassword();
+   private Boolean maskPassword = 
ActiveMQDefaultConfiguration.isDefaultMaskPassword();
 
    private transient String passwordCodec;
 
@@ -1461,12 +1461,12 @@ public class ConfigurationImpl implements 
Configuration, Serializable {
    }
 
    @Override
-   public boolean isMaskPassword() {
+   public Boolean isMaskPassword() {
       return maskPassword;
    }
 
    @Override
-   public ConfigurationImpl setMaskPassword(boolean maskPassword) {
+   public ConfigurationImpl setMaskPassword(Boolean maskPassword) {
       this.maskPassword = maskPassword;
       return this;
    }
@@ -1673,7 +1673,6 @@ public class ConfigurationImpl implements Configuration, 
Serializable {
          return false;
       if (asyncConnectionExecutionEnabled != 
other.asyncConnectionExecutionEnabled)
          return false;
-
       if (bindingsDirectory == null) {
          if (other.bindingsDirectory != null)
             return false;
@@ -1689,11 +1688,13 @@ public class ConfigurationImpl implements 
Configuration, Serializable {
             return false;
       } else if 
(!broadcastGroupConfigurations.equals(other.broadcastGroupConfigurations))
          return false;
+
       if (clusterConfigurations == null) {
          if (other.clusterConfigurations != null)
             return false;
       } else if (!clusterConfigurations.equals(other.clusterConfigurations))
          return false;
+
       if (clusterPassword == null) {
          if (other.clusterPassword != null)
             return false;
@@ -1720,6 +1721,7 @@ public class ConfigurationImpl implements Configuration, 
Serializable {
          return false;
       if (createJournalDir != other.createJournalDir)
          return false;
+
       if (discoveryGroupConfigurations == null) {
          if (other.discoveryGroupConfigurations != null)
             return false;
@@ -1801,8 +1803,15 @@ public class ConfigurationImpl implements Configuration, 
Serializable {
             return false;
       } else if 
(!managementNotificationAddress.equals(other.managementNotificationAddress))
          return false;
-      if (maskPassword != other.maskPassword)
-         return false;
+
+      if (this.maskPassword == null) {
+         if (other.maskPassword != null)
+            return false;
+      } else {
+         if (!this.maskPassword.equals(other.maskPassword))
+            return false;
+      }
+
       if (maxConcurrentPageIO != other.maxConcurrentPageIO)
          return false;
       if (memoryMeasureInterval != other.memoryMeasureInterval)
@@ -1824,7 +1833,6 @@ public class ConfigurationImpl implements Configuration, 
Serializable {
             return false;
       } else if (!name.equals(other.name))
          return false;
-
       if (outgoingInterceptorClassNames == null) {
          if (other.outgoingInterceptorClassNames != null)
             return false;
@@ -1881,6 +1889,7 @@ public class ConfigurationImpl implements Configuration, 
Serializable {
       if (journalDatasync != other.journalDatasync) {
          return false;
       }
+
       if (globalMaxSize != null && !globalMaxSize.equals(other.globalMaxSize)) 
{
          return false;
       }

http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/bb84f679/artemis-server/src/main/java/org/apache/activemq/artemis/core/config/impl/FileSecurityConfiguration.java
----------------------------------------------------------------------
diff --git 
a/artemis-server/src/main/java/org/apache/activemq/artemis/core/config/impl/FileSecurityConfiguration.java
 
b/artemis-server/src/main/java/org/apache/activemq/artemis/core/config/impl/FileSecurityConfiguration.java
index d778aa5..b33a419 100644
--- 
a/artemis-server/src/main/java/org/apache/activemq/artemis/core/config/impl/FileSecurityConfiguration.java
+++ 
b/artemis-server/src/main/java/org/apache/activemq/artemis/core/config/impl/FileSecurityConfiguration.java
@@ -22,7 +22,6 @@ import java.util.Set;
 
 import org.apache.activemq.artemis.core.server.ActiveMQServerLogger;
 import org.apache.activemq.artemis.utils.PasswordMaskingUtil;
-import org.apache.activemq.artemis.utils.SensitiveDataCodec;
 
 @Deprecated
 public class FileSecurityConfiguration extends SecurityConfiguration {
@@ -31,7 +30,7 @@ public class FileSecurityConfiguration extends 
SecurityConfiguration {
 
    private final String rolesUrl;
 
-   private boolean maskPassword;
+   private Boolean maskPassword;
 
    private String passwordCodec;
 
@@ -65,14 +64,7 @@ public class FileSecurityConfiguration extends 
SecurityConfiguration {
       if (started) {
          return;
       }
-      SensitiveDataCodec<String> codec = null;
-      if (maskPassword) {
-         if (passwordCodec != null) {
-            codec = PasswordMaskingUtil.getDefaultCodec();
-         } else {
-            codec = PasswordMaskingUtil.getCodec(passwordCodec);
-         }
-      }
+
       URL theUsersUrl = getClass().getClassLoader().getResource(usersUrl);
 
       if (theUsersUrl == null) {
@@ -94,9 +86,7 @@ public class FileSecurityConfiguration extends 
SecurityConfiguration {
 
       for (String username : keys) {
          String password = userProps.getProperty(username);
-         if (codec != null) {
-            password = codec.decode(password);
-         }
+         password = PasswordMaskingUtil.resolveMask(this.maskPassword, 
password, passwordCodec);
          addUser(username, password);
       }
 

http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/bb84f679/artemis-server/src/main/java/org/apache/activemq/artemis/core/deployers/impl/FileConfigurationParser.java
----------------------------------------------------------------------
diff --git 
a/artemis-server/src/main/java/org/apache/activemq/artemis/core/deployers/impl/FileConfigurationParser.java
 
b/artemis-server/src/main/java/org/apache/activemq/artemis/core/deployers/impl/FileConfigurationParser.java
index 9b9050b..14b0025 100644
--- 
a/artemis-server/src/main/java/org/apache/activemq/artemis/core/deployers/impl/FileConfigurationParser.java
+++ 
b/artemis-server/src/main/java/org/apache/activemq/artemis/core/deployers/impl/FileConfigurationParser.java
@@ -80,7 +80,6 @@ import org.apache.activemq.artemis.utils.ByteUtil;
 import org.apache.activemq.artemis.utils.ClassloadingUtil;
 import org.apache.activemq.artemis.utils.DefaultSensitiveStringCodec;
 import org.apache.activemq.artemis.utils.PasswordMaskingUtil;
-import org.apache.activemq.artemis.utils.SensitiveDataCodec;
 import org.apache.activemq.artemis.utils.XMLConfigurationUtil;
 import org.apache.activemq.artemis.utils.XMLUtil;
 import org.apache.activemq.artemis.utils.critical.CriticalAnalyzerPolicy;
@@ -339,7 +338,7 @@ public final class FileConfigurationParser extends 
XMLConfigurationUtil {
 
       config.setManagementNotificationAddress(new SimpleString(getString(e, 
"management-notification-address", 
config.getManagementNotificationAddress().toString(), 
Validators.NOT_NULL_OR_EMPTY)));
 
-      config.setMaskPassword(getBoolean(e, "mask-password", false));
+      config.setMaskPassword(getBoolean(e, "mask-password", null));
 
       config.setPasswordCodec(getString(e, "password-codec", 
DefaultSensitiveStringCodec.class.getName(), Validators.NOT_NULL_OR_EMPTY));
 
@@ -369,15 +368,11 @@ public final class FileConfigurationParser extends 
XMLConfigurationUtil {
       // parsing cluster password
       String passwordText = getString(e, "cluster-password", null, 
Validators.NO_CHECK);
 
-      final boolean maskText = config.isMaskPassword();
+      final Boolean maskText = config.isMaskPassword();
 
       if (passwordText != null) {
-         if (maskText) {
-            SensitiveDataCodec<String> codec = 
PasswordMaskingUtil.getCodec(config.getPasswordCodec());
-            config.setClusterPassword(codec.decode(passwordText));
-         } else {
-            config.setClusterPassword(passwordText);
-         }
+         String resolvedPassword = PasswordMaskingUtil.resolveMask(maskText, 
passwordText, config.getPasswordCodec());
+         config.setClusterPassword(resolvedPassword);
       }
 
       config.setClusterUser(getString(e, "cluster-user", 
config.getClusterUser(), Validators.NO_CHECK));
@@ -1164,12 +1159,10 @@ public final class FileConfigurationParser extends 
XMLConfigurationUtil {
 
       Map<String, Object> params = configurations.get(0).getParams();
 
-      if (mainConfig.isMaskPassword()) {
-         params.put(ActiveMQDefaultConfiguration.getPropMaskPassword(), 
mainConfig.isMaskPassword());
+      params.put(ActiveMQDefaultConfiguration.getPropMaskPassword(), 
mainConfig.isMaskPassword());
 
-         if (mainConfig.getPasswordCodec() != null) {
-            params.put(ActiveMQDefaultConfiguration.getPropPasswordCodec(), 
mainConfig.getPasswordCodec());
-         }
+      if (mainConfig.getPasswordCodec() != null) {
+         params.put(ActiveMQDefaultConfiguration.getPropPasswordCodec(), 
mainConfig.getPasswordCodec());
       }
 
       return configurations.get(0);
@@ -1187,12 +1180,10 @@ public final class FileConfigurationParser extends 
XMLConfigurationUtil {
 
       Map<String, Object> params = configurations.get(0).getParams();
 
-      if (mainConfig.isMaskPassword()) {
-         params.put(ActiveMQDefaultConfiguration.getPropMaskPassword(), 
mainConfig.isMaskPassword());
+      params.put(ActiveMQDefaultConfiguration.getPropMaskPassword(), 
mainConfig.isMaskPassword());
 
-         if (mainConfig.getPasswordCodec() != null) {
-            params.put(ActiveMQDefaultConfiguration.getPropPasswordCodec(), 
mainConfig.getPasswordCodec());
-         }
+      if (mainConfig.getPasswordCodec() != null) {
+         params.put(ActiveMQDefaultConfiguration.getPropPasswordCodec(), 
mainConfig.getPasswordCodec());
       }
 
       return configurations.get(0);
@@ -1720,9 +1711,6 @@ public final class FileConfigurationParser extends 
XMLConfigurationUtil {
 
       NodeList clusterPassNodes = brNode.getElementsByTagName("password");
       String password = null;
-      boolean maskPassword = mainConfig.isMaskPassword();
-
-      SensitiveDataCodec<String> codec = null;
 
       if (clusterPassNodes.getLength() > 0) {
          Node passNode = clusterPassNodes.item(0);
@@ -1730,10 +1718,7 @@ public final class FileConfigurationParser extends 
XMLConfigurationUtil {
       }
 
       if (password != null) {
-         if (maskPassword) {
-            codec = 
PasswordMaskingUtil.getCodec(mainConfig.getPasswordCodec());
-            password = codec.decode(password);
-         }
+         password = 
PasswordMaskingUtil.resolveMask(mainConfig.isMaskPassword(), password, 
mainConfig.getPasswordCodec());
       } else {
          password = ActiveMQDefaultConfiguration.getDefaultClusterPassword();
       }

http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/bb84f679/artemis-server/src/main/java/org/apache/activemq/artemis/spi/core/security/jaas/LDAPLoginModule.java
----------------------------------------------------------------------
diff --git 
a/artemis-server/src/main/java/org/apache/activemq/artemis/spi/core/security/jaas/LDAPLoginModule.java
 
b/artemis-server/src/main/java/org/apache/activemq/artemis/spi/core/security/jaas/LDAPLoginModule.java
index a1ba4e7..e24f4f6 100644
--- 
a/artemis-server/src/main/java/org/apache/activemq/artemis/spi/core/security/jaas/LDAPLoginModule.java
+++ 
b/artemis-server/src/main/java/org/apache/activemq/artemis/spi/core/security/jaas/LDAPLoginModule.java
@@ -58,6 +58,7 @@ import java.util.Queue;
 import java.util.Set;
 
 import org.apache.activemq.artemis.core.server.ActiveMQServerLogger;
+import org.apache.activemq.artemis.utils.PasswordMaskingUtil;
 import org.jboss.logging.Logger;
 
 public class LDAPLoginModule implements LoginModule {
@@ -83,6 +84,8 @@ public class LDAPLoginModule implements LoginModule {
    private static final String SASL_LOGIN_CONFIG_SCOPE = 
"saslLoginConfigScope";
    private static final String AUTHENTICATE_USER = "authenticateUser";
    private static final String REFERRAL = "referral";
+   private static final String MASK_PASSWORD = "maskPassword";
+   private static final String PASSWORD_CODEC = "passwordCodec";
 
    protected DirContext context;
 
@@ -97,6 +100,8 @@ public class LDAPLoginModule implements LoginModule {
    private boolean isRoleAttributeSet = false;
    private String roleAttributeName = null;
 
+   private String codecClass = null;
+
    @Override
    public void initialize(Subject subject,
                           CallbackHandler callbackHandler,
@@ -105,12 +110,38 @@ public class LDAPLoginModule implements LoginModule {
       this.subject = subject;
       this.handler = callbackHandler;
 
-      config = new LDAPLoginProperty[]{new 
LDAPLoginProperty(INITIAL_CONTEXT_FACTORY, (String) 
options.get(INITIAL_CONTEXT_FACTORY)), new LDAPLoginProperty(CONNECTION_URL, 
(String) options.get(CONNECTION_URL)), new 
LDAPLoginProperty(CONNECTION_USERNAME, (String) 
options.get(CONNECTION_USERNAME)), new LDAPLoginProperty(CONNECTION_PASSWORD, 
(String) options.get(CONNECTION_PASSWORD)), new 
LDAPLoginProperty(CONNECTION_PROTOCOL, (String) 
options.get(CONNECTION_PROTOCOL)), new LDAPLoginProperty(AUTHENTICATION, 
(String) options.get(AUTHENTICATION)), new LDAPLoginProperty(USER_BASE, 
(String) options.get(USER_BASE)), new LDAPLoginProperty(USER_SEARCH_MATCHING, 
(String) options.get(USER_SEARCH_MATCHING)), new 
LDAPLoginProperty(USER_SEARCH_SUBTREE, (String) 
options.get(USER_SEARCH_SUBTREE)), new LDAPLoginProperty(ROLE_BASE, (String) 
options.get(ROLE_BASE)), new LDAPLoginProperty(ROLE_NAME, (String) 
options.get(ROLE_NAME)), new LDAPLoginProperty(ROLE_SEARCH_MATCHING, (String) 
options.get(ROLE_S
 EARCH_MATCHING)), new LDAPLoginProperty(ROLE_SEARCH_SUBTREE, (String) 
options.get(ROLE_SEARCH_SUBTREE)), new LDAPLoginProperty(USER_ROLE_NAME, 
(String) options.get(USER_ROLE_NAME)), new LDAPLoginProperty(EXPAND_ROLES, 
(String) options.get(EXPAND_ROLES)), new 
LDAPLoginProperty(EXPAND_ROLES_MATCHING, (String) 
options.get(EXPAND_ROLES_MATCHING)), new LDAPLoginProperty(REFERRAL, (String) 
options.get(REFERRAL))};
+      config = new LDAPLoginProperty[]{new 
LDAPLoginProperty(INITIAL_CONTEXT_FACTORY, (String) 
options.get(INITIAL_CONTEXT_FACTORY)),
+                                       new LDAPLoginProperty(CONNECTION_URL, 
(String) options.get(CONNECTION_URL)),
+                                       new 
LDAPLoginProperty(CONNECTION_USERNAME, (String) 
options.get(CONNECTION_USERNAME)),
+                                       new 
LDAPLoginProperty(CONNECTION_PASSWORD, (String) 
options.get(CONNECTION_PASSWORD)),
+                                       new 
LDAPLoginProperty(CONNECTION_PROTOCOL, (String) 
options.get(CONNECTION_PROTOCOL)),
+                                       new LDAPLoginProperty(AUTHENTICATION, 
(String) options.get(AUTHENTICATION)),
+                                       new LDAPLoginProperty(USER_BASE, 
(String) options.get(USER_BASE)),
+                                       new 
LDAPLoginProperty(USER_SEARCH_MATCHING, (String) 
options.get(USER_SEARCH_MATCHING)),
+                                       new 
LDAPLoginProperty(USER_SEARCH_SUBTREE, (String) 
options.get(USER_SEARCH_SUBTREE)),
+                                       new LDAPLoginProperty(ROLE_BASE, 
(String) options.get(ROLE_BASE)),
+                                       new LDAPLoginProperty(ROLE_NAME, 
(String) options.get(ROLE_NAME)),
+                                       new 
LDAPLoginProperty(ROLE_SEARCH_MATCHING, (String) 
options.get(ROLE_SEARCH_MATCHING)),
+                                       new 
LDAPLoginProperty(ROLE_SEARCH_SUBTREE, (String) 
options.get(ROLE_SEARCH_SUBTREE)),
+                                       new LDAPLoginProperty(USER_ROLE_NAME, 
(String) options.get(USER_ROLE_NAME)),
+                                       new LDAPLoginProperty(EXPAND_ROLES, 
(String) options.get(EXPAND_ROLES)),
+                                       new 
LDAPLoginProperty(EXPAND_ROLES_MATCHING, (String) 
options.get(EXPAND_ROLES_MATCHING)),
+                                       new LDAPLoginProperty(REFERRAL, 
(String) options.get(REFERRAL))};
+
       if (isLoginPropertySet(AUTHENTICATE_USER)) {
          authenticateUser = 
Boolean.valueOf(getLDAPPropertyValue(AUTHENTICATE_USER));
       }
       isRoleAttributeSet = isLoginPropertySet(ROLE_NAME);
       roleAttributeName = getLDAPPropertyValue(ROLE_NAME);
+      codecClass = (String) options.get(PASSWORD_CODEC);
+   }
+
+   private String getPlainPassword(String password) {
+      try {
+         return PasswordMaskingUtil.resolveMask(null, password, codecClass);
+      } catch (Exception e) {
+         throw new IllegalArgumentException("Failed to decode password", e);
+      }
    }
 
    @Override
@@ -511,7 +542,7 @@ public class LDAPLoginModule implements LoginModule {
          context.removeFromEnvironment(Context.SECURITY_PRINCIPAL);
       }
       if (isLoginPropertySet(CONNECTION_PASSWORD)) {
-         context.addToEnvironment(Context.SECURITY_CREDENTIALS, 
getLDAPPropertyValue(CONNECTION_PASSWORD));
+         context.addToEnvironment(Context.SECURITY_CREDENTIALS, 
getPlainPassword(getLDAPPropertyValue(CONNECTION_PASSWORD)));
       } else {
          context.removeFromEnvironment(Context.SECURITY_CREDENTIALS);
       }
@@ -575,7 +606,7 @@ public class LDAPLoginModule implements LoginModule {
                }
 
                if (isLoginPropertySet(CONNECTION_PASSWORD)) {
-                  env.put(Context.SECURITY_CREDENTIALS, 
getLDAPPropertyValue(CONNECTION_PASSWORD));
+                  env.put(Context.SECURITY_CREDENTIALS, 
getPlainPassword(getLDAPPropertyValue(CONNECTION_PASSWORD)));
                } else {
                   throw new NamingException("Empty password is not allowed");
                }

http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/bb84f679/artemis-server/src/main/java/org/apache/activemq/artemis/utils/XMLConfigurationUtil.java
----------------------------------------------------------------------
diff --git 
a/artemis-server/src/main/java/org/apache/activemq/artemis/utils/XMLConfigurationUtil.java
 
b/artemis-server/src/main/java/org/apache/activemq/artemis/utils/XMLConfigurationUtil.java
index 7ce5280..29cfef9 100644
--- 
a/artemis-server/src/main/java/org/apache/activemq/artemis/utils/XMLConfigurationUtil.java
+++ 
b/artemis-server/src/main/java/org/apache/activemq/artemis/utils/XMLConfigurationUtil.java
@@ -116,7 +116,7 @@ public class XMLConfigurationUtil {
       return getTextBytesAsLongBytes(e, name, def, validator).intValue();
    }
 
-   public static final Boolean getBoolean(final Element e, final String name, 
final boolean def) {
+   public static final Boolean getBoolean(final Element e, final String name, 
final Boolean def) {
       NodeList nl = e.getElementsByTagName(name);
       if (nl.getLength() > 0) {
          return XMLUtil.parseBoolean(nl.item(0));

http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/bb84f679/artemis-server/src/test/java/org/apache/activemq/artemis/core/config/impl/FileConfigurationParserTest.java
----------------------------------------------------------------------
diff --git 
a/artemis-server/src/test/java/org/apache/activemq/artemis/core/config/impl/FileConfigurationParserTest.java
 
b/artemis-server/src/test/java/org/apache/activemq/artemis/core/config/impl/FileConfigurationParserTest.java
index 94d64ec..564372d 100644
--- 
a/artemis-server/src/test/java/org/apache/activemq/artemis/core/config/impl/FileConfigurationParserTest.java
+++ 
b/artemis-server/src/test/java/org/apache/activemq/artemis/core/config/impl/FileConfigurationParserTest.java
@@ -19,10 +19,12 @@ package org.apache.activemq.artemis.core.config.impl;
 import java.io.ByteArrayInputStream;
 import java.nio.charset.StandardCharsets;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 
 import org.apache.activemq.artemis.api.config.ActiveMQDefaultConfiguration;
 import org.apache.activemq.artemis.api.core.SimpleString;
+import org.apache.activemq.artemis.core.config.BridgeConfiguration;
 import org.apache.activemq.artemis.core.config.Configuration;
 import org.apache.activemq.artemis.core.config.FileDeploymentManager;
 import org.apache.activemq.artemis.core.config.HAPolicyConfiguration;
@@ -32,6 +34,7 @@ import 
org.apache.activemq.artemis.core.deployers.impl.FileConfigurationParser;
 import org.apache.activemq.artemis.core.server.ActiveMQServer;
 import org.apache.activemq.artemis.tests.util.ActiveMQTestBase;
 import org.apache.activemq.artemis.utils.DefaultSensitiveStringCodec;
+import org.apache.activemq.artemis.utils.PasswordMaskingUtil;
 import org.junit.Assert;
 import org.junit.Test;
 
@@ -190,6 +193,85 @@ public class FileConfigurationParserTest extends 
ActiveMQTestBase {
       assertEquals("newpassword", config.getClusterPassword());
    }
 
+   @Test
+   public void testParsingDefaultServerConfigWithENCMaskedPwd() throws 
Exception {
+      FileConfigurationParser parser = new FileConfigurationParser();
+
+      String configStr = firstPart + lastPart;
+      ByteArrayInputStream input = new 
ByteArrayInputStream(configStr.getBytes(StandardCharsets.UTF_8));
+
+      Configuration config = parser.parseMainConfig(input);
+
+      String clusterPassword = config.getClusterPassword();
+
+      assertEquals(ActiveMQDefaultConfiguration.getDefaultClusterPassword(), 
clusterPassword);
+
+      //if we add cluster-password, it should be default plain text
+      String clusterPasswordPart = 
"<cluster-password>ENC(5aec0780b12bf225a13ab70c6c76bc8e)</cluster-password>";
+
+      configStr = firstPart + clusterPasswordPart + lastPart;
+
+      config = parser.parseMainConfig(new 
ByteArrayInputStream(configStr.getBytes(StandardCharsets.UTF_8)));
+
+      assertEquals("helloworld", config.getClusterPassword());
+
+      //if we add mask, it should be able to decode correctly
+      DefaultSensitiveStringCodec codec = new DefaultSensitiveStringCodec();
+      String mask = (String) codec.encode("helloworld");
+
+      clusterPasswordPart = "<cluster-password>" + 
PasswordMaskingUtil.wrap(mask) + "</cluster-password>";
+
+      configStr = firstPart + clusterPasswordPart + lastPart;
+
+      config = parser.parseMainConfig(new 
ByteArrayInputStream(configStr.getBytes(StandardCharsets.UTF_8)));
+
+      assertEquals("helloworld", config.getClusterPassword());
+
+      //if we change key, it should be able to decode correctly
+      codec = new DefaultSensitiveStringCodec();
+      Map<String, String> prop = new HashMap<>();
+      prop.put("key", "newkey");
+      codec.init(prop);
+
+      mask = (String) codec.encode("newpassword");
+
+      clusterPasswordPart = "<cluster-password>" + 
PasswordMaskingUtil.wrap(mask) + "</cluster-password>";
+
+      String codecPart = "<password-codec>" + 
"org.apache.activemq.artemis.utils.DefaultSensitiveStringCodec" +
+              ";key=newkey</password-codec>";
+
+      configStr = firstPart + clusterPasswordPart + codecPart + lastPart;
+
+      config = parser.parseMainConfig(new 
ByteArrayInputStream(configStr.getBytes(StandardCharsets.UTF_8)));
+
+      assertEquals("newpassword", config.getClusterPassword());
+
+      configStr = firstPart + bridgePart + lastPart;
+      config = parser.parseMainConfig(new 
ByteArrayInputStream(configStr.getBytes(StandardCharsets.UTF_8)));
+
+      List<BridgeConfiguration> bridgeConfigs = 
config.getBridgeConfigurations();
+      assertEquals(1, bridgeConfigs.size());
+
+      BridgeConfiguration bconfig = bridgeConfigs.get(0);
+
+      assertEquals("helloworld", bconfig.getPassword());
+   }
+
+   private static String bridgePart = "<bridges>\n" +
+           "            <bridge name=\"my-bridge\">\n" +
+           "               <queue-name>sausage-factory</queue-name>\n" +
+           "               
<forwarding-address>mincing-machine</forwarding-address>\n" +
+           "               <filter string=\"name='aardvark'\"/>\n" +
+           "               
<transformer-class-name>org.apache.activemq.artemis.jms.example.HatColourChangeTransformer</transformer-class-name>\n"
 +
+           "               <reconnect-attempts>-1</reconnect-attempts>\n" +
+           "               <user>bridge-user</user>" +
+           "               
<password>ENC(5aec0780b12bf225a13ab70c6c76bc8e)</password>" +
+           "               <static-connectors>\n" +
+           "                  
<connector-ref>remote-connector</connector-ref>\n" +
+           "               </static-connectors>\n" +
+           "            </bridge>\n" +
+           "</bridges>\n";
+
    private static String firstPart = "<core xmlns=\"urn:activemq:core\">" + 
"\n" +
       "<name>ActiveMQ.main.config</name>" + "\n" +
       
"<log-delegate-factory-class-name>org.apache.activemq.artemis.integration.logging.Log4jLogDelegateFactory</log-delegate-factory-class-name>"
 + "\n" +

http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/bb84f679/artemis-server/src/test/java/org/apache/activemq/artemis/core/security/jaas/LDAPLoginModuleMaskPasswordTest.java
----------------------------------------------------------------------
diff --git 
a/artemis-server/src/test/java/org/apache/activemq/artemis/core/security/jaas/LDAPLoginModuleMaskPasswordTest.java
 
b/artemis-server/src/test/java/org/apache/activemq/artemis/core/security/jaas/LDAPLoginModuleMaskPasswordTest.java
new file mode 100644
index 0000000..cfb9934
--- /dev/null
+++ 
b/artemis-server/src/test/java/org/apache/activemq/artemis/core/security/jaas/LDAPLoginModuleMaskPasswordTest.java
@@ -0,0 +1,156 @@
+/*
+ * 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.activemq.artemis.core.security.jaas;
+
+import org.apache.directory.server.annotations.CreateLdapServer;
+import org.apache.directory.server.annotations.CreateTransport;
+import org.apache.directory.server.core.annotations.ApplyLdifFiles;
+import org.apache.directory.server.core.integ.AbstractLdapTestUnit;
+import org.apache.directory.server.core.integ.FrameworkRunner;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.PasswordCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.security.auth.login.FailedLoginException;
+import javax.security.auth.login.LoginContext;
+import javax.security.auth.login.LoginException;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+@RunWith(FrameworkRunner.class)
+@CreateLdapServer(transports = {@CreateTransport(protocol = "LDAP", port = 
1024)})
+@ApplyLdifFiles("test.ldif")
+public class LDAPLoginModuleMaskPasswordTest extends AbstractLdapTestUnit {
+
+   private final String loginConfigSysPropName = 
"java.security.auth.login.config";
+   private String oldLoginConfig;
+
+   @Before
+   public void setLoginConfigSysProperty() {
+      oldLoginConfig = System.getProperty(loginConfigSysPropName, null);
+      System.setProperty(loginConfigSysPropName, 
"src/test/resources/login.config");
+   }
+
+   @After
+   public void resetLoginConfigSysProperty() {
+      if (oldLoginConfig != null) {
+         System.setProperty(loginConfigSysPropName, oldLoginConfig);
+      }
+   }
+
+   @Test
+   public void testLoginMaskedPassword() throws LoginException {
+      LoginContext context = new LoginContext("LDAPLoginMaskedPassword", 
callbacks -> {
+         for (int i = 0; i < callbacks.length; i++) {
+            if (callbacks[i] instanceof NameCallback) {
+               ((NameCallback) callbacks[i]).setName("first");
+            } else if (callbacks[i] instanceof PasswordCallback) {
+               ((PasswordCallback) 
callbacks[i]).setPassword("secret".toCharArray());
+            } else {
+               throw new UnsupportedCallbackException(callbacks[i]);
+            }
+         }
+      });
+      context.login();
+      context.logout();
+   }
+
+   @Test
+   public void testLoginMaskedPasswordUnauthenticated() throws LoginException {
+      LoginContext context = new LoginContext("LDAPLoginMaskedPassword", 
callbacks -> {
+         for (int i = 0; i < callbacks.length; i++) {
+            if (callbacks[i] instanceof NameCallback) {
+               ((NameCallback) callbacks[i]).setName("first");
+            } else if (callbacks[i] instanceof PasswordCallback) {
+               ((PasswordCallback) 
callbacks[i]).setPassword("nosecret".toCharArray());
+            } else {
+               throw new UnsupportedCallbackException(callbacks[i]);
+            }
+         }
+      });
+      try {
+         context.login();
+      } catch (FailedLoginException le) {
+         assertEquals(le.getMessage(), "Password does not match for user: 
first");
+         return;
+      }
+      fail("Should have failed authenticating");
+   }
+
+   @Test
+   public void testLoginExternalCodec() throws LoginException {
+      LoginContext context = new 
LoginContext("LDAPLoginExternalPasswordCodec", callbacks -> {
+         for (int i = 0; i < callbacks.length; i++) {
+            if (callbacks[i] instanceof NameCallback) {
+               ((NameCallback) callbacks[i]).setName("first");
+            } else if (callbacks[i] instanceof PasswordCallback) {
+               ((PasswordCallback) 
callbacks[i]).setPassword("secret".toCharArray());
+            } else {
+               throw new UnsupportedCallbackException(callbacks[i]);
+            }
+         }
+      });
+
+      context.login();
+      context.logout();
+   }
+
+   @Test
+   public void testLoginExternalCodec2() throws LoginException {
+      LoginContext context = new 
LoginContext("LDAPLoginExternalPasswordCodec2", callbacks -> {
+         for (int i = 0; i < callbacks.length; i++) {
+            if (callbacks[i] instanceof NameCallback) {
+               ((NameCallback) callbacks[i]).setName("first");
+            } else if (callbacks[i] instanceof PasswordCallback) {
+               ((PasswordCallback) 
callbacks[i]).setPassword("secret".toCharArray());
+            } else {
+               throw new UnsupportedCallbackException(callbacks[i]);
+            }
+         }
+      });
+
+      context.login();
+      context.logout();
+   }
+
+   @Test
+   public void testLoginExternalCodecUnauthenticated() throws LoginException {
+      LoginContext context = new 
LoginContext("LDAPLoginExternalPasswordCodec", callbacks -> {
+         for (int i = 0; i < callbacks.length; i++) {
+            if (callbacks[i] instanceof NameCallback) {
+               ((NameCallback) callbacks[i]).setName("first");
+            } else if (callbacks[i] instanceof PasswordCallback) {
+               ((PasswordCallback) 
callbacks[i]).setPassword("nosecret".toCharArray());
+            } else {
+               throw new UnsupportedCallbackException(callbacks[i]);
+            }
+         }
+      });
+      try {
+         context.login();
+      } catch (FailedLoginException le) {
+         assertEquals(le.getMessage(), "Password does not match for user: 
first");
+         return;
+      }
+      fail("Should have failed authenticating");
+   }
+}

http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/bb84f679/artemis-server/src/test/java/org/apache/activemq/artemis/core/security/jaas/PropertiesLoginModuleTest.java
----------------------------------------------------------------------
diff --git 
a/artemis-server/src/test/java/org/apache/activemq/artemis/core/security/jaas/PropertiesLoginModuleTest.java
 
b/artemis-server/src/test/java/org/apache/activemq/artemis/core/security/jaas/PropertiesLoginModuleTest.java
index 1ab5dba..eb6c9fa 100644
--- 
a/artemis-server/src/test/java/org/apache/activemq/artemis/core/security/jaas/PropertiesLoginModuleTest.java
+++ 
b/artemis-server/src/test/java/org/apache/activemq/artemis/core/security/jaas/PropertiesLoginModuleTest.java
@@ -77,6 +77,13 @@ public class PropertiesLoginModuleTest extends Assert {
    }
 
    @Test
+   public void testLoginMasked() throws LoginException {
+      LoginContext context = new LoginContext("PropertiesLogin", new 
UserPassHandler("third", "helloworld"));
+      context.login();
+      context.logout();
+   }
+
+   @Test
    public void testLoginReload() throws Exception {
       File targetPropDir = new File("target/loginReloadTest");
       File usersFile = new File(targetPropDir, "users.properties");

http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/bb84f679/artemis-server/src/test/resources/login.config
----------------------------------------------------------------------
diff --git a/artemis-server/src/test/resources/login.config 
b/artemis-server/src/test/resources/login.config
index 997bfe5..8e531ca 100644
--- a/artemis-server/src/test/resources/login.config
+++ b/artemis-server/src/test/resources/login.config
@@ -125,3 +125,62 @@ OpenLdapConfiguration {
         roleSearchSubtree=true
         ;
 };
+
+LDAPLoginMaskedPassword {
+    org.apache.activemq.artemis.spi.core.security.jaas.LDAPLoginModule required
+        debug=true
+        initialContextFactory=com.sun.jndi.ldap.LdapCtxFactory
+        connectionURL="ldap://localhost:1024";
+        connectionUsername="uid=admin,ou=system"
+        connectionPassword="ENC(-41e444c3ed07d6dd)"
+        connectionProtocol=s
+        authentication=simple
+        userBase="ou=system"
+        userSearchMatching="(uid={0})"
+        userSearchSubtree=false
+        roleBase="ou=system"
+        roleName=cn
+        roleSearchMatching="(member=uid={1},ou=system)"
+        roleSearchSubtree=false
+        ;
+};
+
+LDAPLoginExternalPasswordCodec {
+    org.apache.activemq.artemis.spi.core.security.jaas.LDAPLoginModule required
+        debug=true
+        
passwordCodec="org.apache.activemq.artemis.utils.DefaultSensitiveStringCodec;key=helloworld"
+        initialContextFactory=com.sun.jndi.ldap.LdapCtxFactory
+        connectionURL="ldap://localhost:1024";
+        connectionUsername="uid=admin,ou=system"
+        connectionPassword="ENC(-170b9ef34d79ed12)"
+        connectionProtocol=s
+        authentication=simple
+        userBase="ou=system"
+        userSearchMatching="(uid={0})"
+        userSearchSubtree=false
+        roleBase="ou=system"
+        roleName=dummyRoleName
+        roleSearchMatching="(uid={1})"
+        roleSearchSubtree=false
+        ;
+};
+
+LDAPLoginExternalPasswordCodec2 {
+    org.apache.activemq.artemis.spi.core.security.jaas.LDAPLoginModule required
+        debug=true
+        
passwordCodec="org.apache.activemq.artemis.utils.MaskPasswordResolvingTest$SimplePasswordCodec"
+        initialContextFactory=com.sun.jndi.ldap.LdapCtxFactory
+        connectionURL="ldap://localhost:1024";
+        connectionUsername="uid=admin,ou=system"
+        connectionPassword="ENC(momsword)"
+        connectionProtocol=s
+        authentication=simple
+        userBase="ou=system"
+        userSearchMatching="(uid={0})"
+        userSearchSubtree=false
+        roleBase="ou=system"
+        roleName=dummyRoleName
+        roleSearchMatching="(uid={1})"
+        roleSearchSubtree=false
+        ;
+};

http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/bb84f679/artemis-server/src/test/resources/users.properties
----------------------------------------------------------------------
diff --git a/artemis-server/src/test/resources/users.properties 
b/artemis-server/src/test/resources/users.properties
index 1087b0b..c1a6b47 100644
--- a/artemis-server/src/test/resources/users.properties
+++ b/artemis-server/src/test/resources/users.properties
@@ -17,3 +17,4 @@
 
 first=secret
 second=password
+third=ENC(1024:439F45267508BB4F02150B9AAFB8D774AB7FCDDE9B19D096F318787487F7BD17:78818E53AEE8AF26A34A38C1498D1CDA5636861D2FE9804FEDE3656D0BC05696191A027F095DF109EC8F6385FAE9971915449EC808945A0F5907B29D5F9D44B7)
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/bb84f679/artemis-web/pom.xml
----------------------------------------------------------------------
diff --git a/artemis-web/pom.xml b/artemis-web/pom.xml
index a9be5c0..4edc47a 100644
--- a/artemis-web/pom.xml
+++ b/artemis-web/pom.xml
@@ -69,6 +69,13 @@
          <version>${project.version}</version>
       </dependency>
       <dependency>
+         <groupId>org.apache.activemq</groupId>
+         <artifactId>artemis-commons</artifactId>
+         <version>${project.version}</version>
+         <classifier>tests</classifier>
+         <scope>test</scope>
+      </dependency>
+      <dependency>
          <groupId>io.netty</groupId>
          <artifactId>netty-buffer</artifactId>
       </dependency>

http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/bb84f679/artemis-web/src/main/java/org/apache/activemq/artemis/component/WebServerComponent.java
----------------------------------------------------------------------
diff --git 
a/artemis-web/src/main/java/org/apache/activemq/artemis/component/WebServerComponent.java
 
b/artemis-web/src/main/java/org/apache/activemq/artemis/component/WebServerComponent.java
index 9964c71..d85d621 100644
--- 
a/artemis-web/src/main/java/org/apache/activemq/artemis/component/WebServerComponent.java
+++ 
b/artemis-web/src/main/java/org/apache/activemq/artemis/component/WebServerComponent.java
@@ -68,12 +68,12 @@ public class WebServerComponent implements 
ExternalComponent {
       if ("https".equals(scheme)) {
          SslContextFactory sslFactory = new SslContextFactory();
          sslFactory.setKeyStorePath(webServerConfig.keyStorePath == null ? 
artemisInstance + "/etc/keystore.jks" : webServerConfig.keyStorePath);
-         sslFactory.setKeyStorePassword(webServerConfig.keyStorePassword == 
null ? "password" : webServerConfig.keyStorePassword);
+         sslFactory.setKeyStorePassword(webServerConfig.getKeyStorePassword() 
== null ? "password" : webServerConfig.getKeyStorePassword());
          if (webServerConfig.clientAuth != null) {
             sslFactory.setNeedClientAuth(webServerConfig.clientAuth);
             if (webServerConfig.clientAuth) {
                sslFactory.setTrustStorePath(webServerConfig.trustStorePath);
-               
sslFactory.setTrustStorePassword(webServerConfig.trustStorePassword);
+               
sslFactory.setTrustStorePassword(webServerConfig.getTrustStorePassword());
             }
          }
 

http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/bb84f679/artemis-web/src/test/java/org/apache/activemq/cli/test/WebServerComponentTest.java
----------------------------------------------------------------------
diff --git 
a/artemis-web/src/test/java/org/apache/activemq/cli/test/WebServerComponentTest.java
 
b/artemis-web/src/test/java/org/apache/activemq/cli/test/WebServerComponentTest.java
index 00691ed..1178147 100644
--- 
a/artemis-web/src/test/java/org/apache/activemq/cli/test/WebServerComponentTest.java
+++ 
b/artemis-web/src/test/java/org/apache/activemq/cli/test/WebServerComponentTest.java
@@ -18,6 +18,7 @@ package org.apache.activemq.cli.test;
 
 import javax.net.ssl.SSLContext;
 import javax.net.ssl.SSLEngine;
+import java.io.File;
 import java.net.URI;
 import java.net.URISyntaxException;
 import java.util.ArrayList;
@@ -43,9 +44,11 @@ import io.netty.handler.codec.http.HttpRequest;
 import io.netty.handler.codec.http.HttpVersion;
 import io.netty.handler.ssl.SslHandler;
 import io.netty.util.CharsetUtil;
+import org.apache.activemq.artemis.cli.factory.xml.XmlBrokerFactoryHandler;
 import org.apache.activemq.artemis.component.WebServerComponent;
 import org.apache.activemq.artemis.core.remoting.impl.ssl.SSLSupport;
 import org.apache.activemq.artemis.core.server.ActiveMQComponent;
+import org.apache.activemq.artemis.dto.BrokerDTO;
 import org.apache.activemq.artemis.dto.WebServerDTO;
 import org.junit.After;
 import org.junit.Assert;
@@ -163,7 +166,7 @@ public class WebServerComponentTest extends Assert {
       webServerDTO.bind = "https://localhost:0";;
       webServerDTO.path = "webapps";
       webServerDTO.keyStorePath = "./src/test/resources/server.keystore";
-      webServerDTO.keyStorePassword = "password";
+      webServerDTO.setKeyStorePassword("password");
 
       WebServerComponent webServerComponent = new WebServerComponent();
       Assert.assertFalse(webServerComponent.isStarted());
@@ -174,7 +177,7 @@ public class WebServerComponentTest extends Assert {
       // Make the connection attempt.
       String keyStoreProvider = "JKS";
 
-      SSLContext context = SSLSupport.createContext(keyStoreProvider, 
webServerDTO.keyStorePath, webServerDTO.keyStorePassword, keyStoreProvider, 
webServerDTO.keyStorePath, webServerDTO.keyStorePassword);
+      SSLContext context = SSLSupport.createContext(keyStoreProvider, 
webServerDTO.keyStorePath, webServerDTO.getKeyStorePassword(), 
keyStoreProvider, webServerDTO.keyStorePath, 
webServerDTO.getKeyStorePassword());
 
       SSLEngine engine = context.createSSLEngine();
       engine.setUseClientMode(true);
@@ -215,10 +218,10 @@ public class WebServerComponentTest extends Assert {
       webServerDTO.bind = "https://localhost:0";;
       webServerDTO.path = "webapps";
       webServerDTO.keyStorePath = "./src/test/resources/server.keystore";
-      webServerDTO.keyStorePassword = "password";
+      webServerDTO.setKeyStorePassword("password");
       webServerDTO.clientAuth = true;
       webServerDTO.trustStorePath = "./src/test/resources/server.keystore";
-      webServerDTO.trustStorePassword = "password";
+      webServerDTO.setTrustStorePassword("password");
 
       WebServerComponent webServerComponent = new WebServerComponent();
       Assert.assertFalse(webServerComponent.isStarted());
@@ -229,7 +232,7 @@ public class WebServerComponentTest extends Assert {
       // Make the connection attempt.
       String keyStoreProvider = "JKS";
 
-      SSLContext context = SSLSupport.createContext(keyStoreProvider, 
webServerDTO.keyStorePath, webServerDTO.keyStorePassword, keyStoreProvider, 
webServerDTO.trustStorePath, webServerDTO.trustStorePassword);
+      SSLContext context = SSLSupport.createContext(keyStoreProvider, 
webServerDTO.keyStorePath, webServerDTO.getKeyStorePassword(), 
keyStoreProvider, webServerDTO.trustStorePath, 
webServerDTO.getTrustStorePassword());
 
       SSLEngine engine = context.createSSLEngine();
       engine.setUseClientMode(true);
@@ -264,6 +267,44 @@ public class WebServerComponentTest extends Assert {
       Assert.assertFalse(webServerComponent.isStarted());
    }
 
+   @Test
+   public void testDefaultMaskPasswords() throws Exception {
+      File bootstrap = new File("./target/test-classes/bootstrap_web.xml");
+      File brokerHome = new File("./target");
+      XmlBrokerFactoryHandler xmlHandler = new XmlBrokerFactoryHandler();
+      BrokerDTO broker = xmlHandler.createBroker(bootstrap.toURI(), 
brokerHome.getAbsolutePath(), brokerHome.getAbsolutePath(), brokerHome.toURI());
+      assertNotNull(broker.web);
+      assertNull(broker.web.passwordCodec);
+   }
+
+   @Test
+   public void testMaskPasswords() throws Exception {
+      final String keyPassword = "keypass";
+      final String trustPassword = "trustpass";
+      File bootstrap = new 
File("./target/test-classes/bootstrap_secure_web.xml");
+      File brokerHome = new File("./target");
+      XmlBrokerFactoryHandler xmlHandler = new XmlBrokerFactoryHandler();
+      BrokerDTO broker = xmlHandler.createBroker(bootstrap.toURI(), 
brokerHome.getAbsolutePath(), brokerHome.getAbsolutePath(), brokerHome.toURI());
+      assertNotNull(broker.web);
+      assertEquals(keyPassword, broker.web.getKeyStorePassword());
+      assertEquals(trustPassword, broker.web.getTrustStorePassword());
+   }
+
+   @Test
+   public void testMaskPasswordCodec() throws Exception {
+      final String keyPassword = "keypass";
+      final String trustPassword = "trustpass";
+      File bootstrap = new 
File("./target/test-classes/bootstrap_web_codec.xml");
+      File brokerHome = new File("./target");
+      XmlBrokerFactoryHandler xmlHandler = new XmlBrokerFactoryHandler();
+      BrokerDTO broker = xmlHandler.createBroker(bootstrap.toURI(), 
brokerHome.getAbsolutePath(), brokerHome.getAbsolutePath(), brokerHome.toURI());
+      assertNotNull(broker.web);
+      assertNotNull("password codec not picked up!", broker.web.passwordCodec);
+
+      assertEquals(keyPassword, broker.web.getKeyStorePassword());
+      assertEquals(trustPassword, broker.web.getTrustStorePassword());
+   }
+
    class ClientHandler extends SimpleChannelInboundHandler<HttpObject> {
 
       private CountDownLatch latch;

http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/bb84f679/artemis-web/src/test/resources/bootstrap_secure_web.xml
----------------------------------------------------------------------
diff --git a/artemis-web/src/test/resources/bootstrap_secure_web.xml 
b/artemis-web/src/test/resources/bootstrap_secure_web.xml
new file mode 100644
index 0000000..affa9ab
--- /dev/null
+++ b/artemis-web/src/test/resources/bootstrap_secure_web.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!--
+  ~ 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.
+  -->
+
+<broker xmlns="http://activemq.org/schema";>
+
+   <jaas-security domain="activemq"/>
+
+   <!-- artemis.URI.instance is parsed from artemis.instance by the CLI 
startup.
+        This is to avoid situations where you could have spaces or special 
characters on this URI -->
+   <server configuration="${artemis.URI.instance}/etc/broker.xml"/>
+
+   <!-- The web server is only bound to localhost by default -->
+   <web bind="https://localhost:8443"; path="web" 
keyStorePassword="ENC(-5a2376c61c668aaf)" 
trustStorePassword="ENC(3d617352d12839eb71208edf41d66b34)">
+       <app url="activemq-branding" war="activemq-branding.war"/>
+   </web>
+
+
+</broker>
+

http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/bb84f679/artemis-web/src/test/resources/bootstrap_web.xml
----------------------------------------------------------------------
diff --git a/artemis-web/src/test/resources/bootstrap_web.xml 
b/artemis-web/src/test/resources/bootstrap_web.xml
new file mode 100644
index 0000000..847a869
--- /dev/null
+++ b/artemis-web/src/test/resources/bootstrap_web.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!--
+  ~ 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.
+  -->
+
+<broker xmlns="http://activemq.org/schema";>
+
+   <jaas-security domain="activemq"/>
+
+   <!-- artemis.URI.instance is parsed from artemis.instance by the CLI 
startup.
+        This is to avoid situations where you could have spaces or special 
characters on this URI -->
+   <server configuration="${artemis.URI.instance}/etc/broker.xml"/>
+
+   <!-- The web server is only bound to localhost by default -->
+   <web bind="http://localhost:8161"; path="web">
+       <app url="activemq-branding" war="activemq-branding.war"/>
+   </web>
+
+
+</broker>
+

http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/bb84f679/artemis-web/src/test/resources/bootstrap_web_codec.xml
----------------------------------------------------------------------
diff --git a/artemis-web/src/test/resources/bootstrap_web_codec.xml 
b/artemis-web/src/test/resources/bootstrap_web_codec.xml
new file mode 100644
index 0000000..7b53515
--- /dev/null
+++ b/artemis-web/src/test/resources/bootstrap_web_codec.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!--
+  ~ 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.
+  -->
+
+<broker xmlns="http://activemq.org/schema";>
+
+   <jaas-security domain="activemq"/>
+
+   <!-- artemis.URI.instance is parsed from artemis.instance by the CLI 
startup.
+        This is to avoid situations where you could have spaces or special 
characters on this URI -->
+   <server configuration="${artemis.URI.instance}/etc/broker.xml"/>
+
+   <!-- The web server is only bound to localhost by default -->
+   <web bind="https://localhost:8443"; path="web" 
passwordCodec="org.apache.activemq.artemis.utils.MaskPasswordResolvingTest$SimplePasswordCodec"
 keyStorePassword="ENC(youneverknow)" trustStorePassword="ENC(youcanguess)">
+       <app url="console" war="console.war"/>
+   </web>
+
+
+</broker>
+

Reply via email to