NO-JIRA improve password masking doc & code

Move password masking documentation into its own chapter and tweak it a
bit for clarity and comprehensiveness.


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

Branch: refs/heads/master
Commit: 714655a051e70b44ad65206ca30ef3b78ca0a0f6
Parents: ea9b12b
Author: Justin Bertram <jbert...@apache.org>
Authored: Tue Sep 5 14:30:40 2017 -0500
Committer: Clebert Suconic <clebertsuco...@apache.org>
Committed: Tue Sep 5 16:40:38 2017 -0400

----------------------------------------------------------------------
 .../artemis/utils/PasswordMaskingUtil.java      |   4 +-
 .../artemis/utils/SecureHashProcessor.java      |   7 +-
 docs/user-manual/en/SUMMARY.md                  |   1 +
 docs/user-manual/en/configuration-index.md      | 271 +------------------
 docs/user-manual/en/masking-passwords.md        | 254 +++++++++++++++++
 docs/user-manual/en/security.md                 |  15 +
 6 files changed, 276 insertions(+), 276 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/714655a0/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 3fe2ea1..dbc20c5 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
@@ -54,7 +54,7 @@ public final class PasswordMaskingUtil {
       static {
          HashProcessor processor = null;
          Exception exception = null;
-         final String codecDesc = 
"org.apache.activemq.artemis.utils.DefaultSensitiveStringCodec;algorithm=one-way";
+         final String codecDesc = new 
StringBuilder().append(DefaultSensitiveStringCodec.class.getName()).append(";").append(DefaultSensitiveStringCodec.ALGORITHM).append("=").append(DefaultSensitiveStringCodec.ONE_WAY).toString();
          try {
             final DefaultSensitiveStringCodec codec = 
(DefaultSensitiveStringCodec) PasswordMaskingUtil.getCodec(codecDesc);
             processor = new SecureHashProcessor(codec);
@@ -83,7 +83,7 @@ public final class PasswordMaskingUtil {
    }
 
    private static boolean isEncoded(String storedPassword) {
-      return storedPassword == null || (storedPassword.startsWith("ENC(") && 
storedPassword.endsWith(")"));
+      return storedPassword == null || 
(storedPassword.startsWith(SecureHashProcessor.BEGIN_HASH) && 
storedPassword.endsWith(SecureHashProcessor.END_HASH));
    }
 
    public static HashProcessor getHashProcessor() {

http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/714655a0/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 81db051..8e9cd5c 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
@@ -16,13 +16,10 @@
  */
 package org.apache.activemq.artemis.utils;
 
-/**
- * Hash function
- */
 public class SecureHashProcessor implements HashProcessor {
 
-   private static final String BEGIN_HASH = "ENC(";
-   private static final String END_HASH = ")";
+   public static final String BEGIN_HASH = "ENC(";
+   public static final String END_HASH = ")";
 
    private DefaultSensitiveStringCodec codec;
 

http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/714655a0/docs/user-manual/en/SUMMARY.md
----------------------------------------------------------------------
diff --git a/docs/user-manual/en/SUMMARY.md b/docs/user-manual/en/SUMMARY.md
index 68facdc..1a2f531 100644
--- a/docs/user-manual/en/SUMMARY.md
+++ b/docs/user-manual/en/SUMMARY.md
@@ -39,6 +39,7 @@
 * [Management](management.md)
 * [Management Console](management-console.md)
 * [Security](security.md)
+* [Masking Passwords](masking-passwords.md)
 * [Broker Plugins](broker-plugins.md)
 * [Resource Limits](resource-limits.md)
 * [The JMS Bridge](jms-bridge.md)

http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/714655a0/docs/user-manual/en/configuration-index.md
----------------------------------------------------------------------
diff --git a/docs/user-manual/en/configuration-index.md 
b/docs/user-manual/en/configuration-index.md
index 5311515..05e062e 100644
--- a/docs/user-manual/en/configuration-index.md
+++ b/docs/user-manual/en/configuration-index.md
@@ -84,7 +84,7 @@ Name | Description
 [large-messages-directory](large-messages.md "Configuring the server")         
 |  the directory to store large messages. Default=data/largemessages
 [management-address](management.md "Configuring Core Management")   |  the 
name of the management address to send management messages to. 
Default=activemq.management
 [management-notification-address](management.md "Configuring The Core 
Management Notification Address") |  the name of the address that consumers 
bind to receive management notifications. Default=activemq.notifications
-[mask-password](configuration-index.md "Using Masked Passwords in 
Configuration Files")  |  This option controls whether passwords in server 
configuration need be masked. If set to "true" the passwords are masked. 
Default=false
+[mask-password](masking-passwords.md "Masking Passwords")  |  This option 
controls whether passwords in server configuration need be masked. If set to 
"true" the passwords are masked. Default=false
 [max-saved-replicated-journals-size](ha.md#data-replication)                   
                                             |    This specifies how many times 
a replicated backup server can restart after moving its files on start. Once 
there are this number of backup journal files the server will stop permanently 
after if fails back. -1 Means no Limit, 0 don't keep a copy at all, Default=2
 [max-disk-usage](paging.md#max-disk-usage) | The max percentage of data we 
should use from disks. The System will block while the disk is full. Default=100
 [memory-measure-interval](perf-tuning.md)                                      
                       |  frequency to sample JVM memory in ms (or -1 to 
disable memory sampling). Default=-1
@@ -94,6 +94,7 @@ Name | Description
 [message-counter-sample-period](management.md "Configuring Message Counters")  
               |  the sample period (in ms) to use for message counters. 
Default=10000
 [message-expiry-scan-period](message-expiry.md "Configuring The Expiry Reaper 
Thread")          |  how often (in ms) to scan for expired messages. 
Default=30000
 [message-expiry-thread-priority](message-expiry.md "Configuring The Expiry 
Reaper Thread")      |  the priority of the thread expiring messages. Default=3
+[password-codec](masking-passwords.md "Masking Passwords")                     
                 |  the name of the class (and optional configuration 
properties) used to decode masked passwords. Only valid when `mask-password` is 
`true`. Default=empty
 [page-max-concurrent-io](paging.md "Paging Mode")                              
                 |  The max number of concurrent reads allowed on paging. 
Default=5
 [paging-directory](paging.md "Configuration")                                  
                 |  the directory to store paged messages in. 
Default=data/paging
 [persist-delivery-count-before-delivery](undelivered-messages.md "Delivery 
Count Persistence")  |  True means that the delivery count is persisted before 
delivery. False means that this only happens after a message has been 
cancelled. Default=false
@@ -255,271 +256,3 @@ Name | Description
 [permission.type ](security.md "Role based security for addresses")            
         |  the type of permission
 [permission.roles ](security.md "Role based security for addresses")           
         |  a comma-separated list of roles to apply the permission to
 
-
-
-Using Masked Passwords in Configuration Files
----------------------------------------------
-
-By default all passwords in Apache ActiveMQ Artemis server's configuration 
files are in
-plain text form. This usually poses no security issues as those files
-should be well protected from unauthorized accessing. However, in some
-circumstances a user doesn't want to expose its passwords to more eyes
-than necessary.
-
-Apache ActiveMQ Artemis can be configured to use 'masked' passwords in its
-configuration files. A masked password is an obscure string
-representation of a real password. To mask a password a user will use an
-'encoder'. The encoder takes in the real password and outputs the masked
-version. A user can then replace the real password in the configuration
-files with the new masked password. When Apache ActiveMQ Artemis loads a masked
-password, it uses a suitable 'decoder' to decode it into real password.
-
-Apache ActiveMQ Artemis provides a default password encoder and decoder. 
Optionally
-users can use or implement their own encoder and decoder for masking the
-passwords.
-
-### Password Masking in Server Configuration File
-
-#### The password masking property
-
-The server configuration file has a property that defines the default
-masking behaviors over the entire file scope.
-
-`mask-password`: this boolean type property indicates if a password
-should be masked or not. Set it to "true" if you want your passwords
-masked. The default value is "false".
-
-#### Specific masking behaviors
-
-##### cluster-password
-
-The nature of the value of cluster-password is subject to the value of
-property 'mask-password'. If it is true the cluster-password is masked.
-
-##### Passwords in connectors and acceptors
-
-In the server configuration, Connectors and Acceptors sometimes needs to
-specify passwords. For example if a users wants to use an SSL-enabled
-NettyAcceptor, it can specify a key-store-password and a
-trust-store-password. Because Acceptors and Connectors are pluggable
-implementations, each transport will have different password masking
-needs.
-
-When a Connector or Acceptor configuration is initialised, Apache ActiveMQ 
Artemis will
-add the "mask-password" and "password-codec" values to the Connector or
-Acceptors params using the keys `activemq.usemaskedpassword` and
-`activemq.passwordcodec` respectively. The Netty and InVM
-implementations will use these as needed and any other implementations
-will have access to these to use if they so wish.
-
-##### Passwords in Core Bridge configurations
-
-Core Bridges are configured in the server configuration file and so the
-masking of its 'password' properties follows the same rules as that of
-'cluster-password'.
-
-#### Examples
-
-The following table summarizes the relations among the above-mentioned
-properties
-
-  mask-password  | cluster-password  | acceptor/connector passwords |  bridge 
password
-  :------------- | :---------------- | :--------------------------- | 
:---------------
-  absent   |       plain text     |    plain text       |              plain 
text
-  false    |       plain text     |    plain text       |              plain 
text
-  true     |       masked         |    masked           |              masked
-
-Examples
-
-Note: In the following examples if related attributed or properties are
-absent, it means they are not specified in the configure file.
-
-example 1
-
-```xml
-<cluster-password>bbc</cluster-password>
-```
-
-This indicates the cluster password is a plain text value ("bbc").
-
-example 2
-
-```xml
-<mask-password>true</mask-password>
-<cluster-password>80cf731af62c290</cluster-password>
-```
-
-This indicates the cluster password is a masked value and Apache ActiveMQ 
Artemis will
-use its built-in decoder to decode it. All other passwords in the
-configuration file, Connectors, Acceptors and Bridges, will also use
-masked passwords.
-
-### JMS Bridge password masking
-
-The JMS Bridges are configured and deployed as separate beans so they
-need separate configuration to control the password masking. A JMS
-Bridge has two password parameters in its constructor, SourcePassword
-and TargetPassword. It uses the following two optional properties to
-control their masking:
-
-`useMaskedPassword` -- If set to "true" the passwords are masked.
-Default is false.
-
-`passwordCodec` -- Class name and its parameters for the Decoder used to
-decode the masked password. Ignored if `useMaskedPassword` is false. The
-format of this property is a full qualified class name optionally
-followed by key/value pairs, separated by semi-colons. For example:
-
-```xml
-<property name="useMaskedPassword">true</property>
-<property name="passwordCodec">com.foo.FooDecoder;key=value</property>
-```
-
-Apache ActiveMQ Artemis will load this property and initialize the class with a
-parameter map containing the "key"-\>"value" pair. If `passwordCodec` is
-not specified, the built-in decoder is used.
-
-### Masking passwords in ActiveMQ Artemis ResourceAdapters and MDB activation 
configurations
-
-Both ra.xml and MDB activation configuration have a 'password' property
-that can be masked. They are controlled by the following two optional
-Resource Adapter properties in ra.xml:
-
-`UseMaskedPassword` -- If setting to "true" the passwords are masked.
-Default is false.
-
-`PasswordCodec` -- Class name and its parameters for the Decoder used to
-decode the masked password. Ignored if UseMaskedPassword is false. The
-format of this property is a full qualified class name optionally
-followed by key/value pairs. It is the same format as that for JMS
-Bridges. Example:
-
-```xml
-<config-property>
-  <config-property-name>UseMaskedPassword</config-property-name>
-  <config-property-type>boolean</config-property-type>
-  <config-property-value>true</config-property-value>
-</config-property>
-<config-property>
-  <config-property-name>PasswordCodec</config-property-name>
-  <config-property-type>java.lang.String</config-property-type>
-  
<config-property-value>com.foo.ADecoder;key=helloworld</config-property-value>
-</config-property>
-```
-
-With this configuration, both passwords in ra.xml and all of its MDBs
-will have to be in masked form.
-
-### Masking passwords in artemis-users.properties
-
-Apache ActiveMQ Artemis's built-in security manager uses plain properties files
-where the user passwords are specified in hash forms by default. 
-
-Please use Artemis CLI command to add a password. For example
-
-```sh
-    ./artemis user add --username guest --password guest --role admin
-```
-
-### Choosing a decoder for password masking
-
-As described in the previous sections, all password masking requires a
-decoder. A decoder uses an algorithm to convert a masked password into
-its original clear text form in order to be used in various security
-operations. The algorithm used for decoding must match that for
-encoding. Otherwise the decoding may not be successful.
-
-For user's convenience Apache ActiveMQ Artemis provides a default built-in 
Decoder.
-However a user can if they so wish implement their own.
-
-#### The built-in Decoder
-
-Whenever no decoder is specified in the configuration file, the built-in
-decoder is used. The class name for the built-in decoder is
-org.apache.activemq.artemis.utils.DefaultSensitiveStringCodec. It has both
-encoding and decoding capabilities. It uses java.crypto.Cipher utilities
-to encrypt (encode) a plaintext password and decrypt a mask string using
-same algorithm. Using this decoder/encoder is pretty straightforward. To
-get a mask for a password, just run the main class at 
org.apache.activemq.artemis.utils.DefaultSensitiveStringCodec.
-
-An easy way to do it is through 
activemq-tools-<VERSION>-jar-with-dependencies.jar since it has all the 
dependencies:
-
-```sh
-    java -cp artemis-tools-1.0.0-jar-with-dependencies.jar 
org.apache.activemq.artemis.utils.DefaultSensitiveStringCodec "your plaintext 
password"
-```
-
-If you don't want to use the jar-with-dependencies, make sure the classpath is 
correct. You'll get something like
-
-```
-    Encoded password: 80cf731af62c290
-```
-
-Just copy "80cf731af62c290" and replace your plaintext password with it.
-
-#### Using a custom decoder
-
-It is possible to use a custom decoder rather than the built-in one.
-Simply make sure the decoder is in Apache ActiveMQ Artemis's classpath. The 
custom decoder
-can also be service loaded rather than class loaded, if the decoder's service 
provider is installed in the classpath.
-Then configure the server to use it as follows:
-
-```xml
-    
<password-codec>com.foo.SomeDecoder;key1=value1;key2=value2</password-codec>
-```
-
-If your decoder needs params passed to it you can do this via key/value
-pairs when configuring. For instance if your decoder needs say a
-"key-location" parameter, you can define like so:
-
-```xml
-    
<password-codec>com.foo.NewDecoder;key-location=/some/url/to/keyfile</password-codec>
-```
-
-Then configure your cluster-password like this:
-
-```xml
-    <mask-password>true</mask-password>
-    <cluster-password>masked_password</cluster-password>
-```
-
-When Apache ActiveMQ Artemis reads the cluster-password it will initialize the
-NewDecoder and use it to decode "mask\_password". It also process all
-passwords using the new defined decoder.
-
-#### Implementing your own codecs
-
-To use a different decoder than the built-in one, you either pick one
-from existing libraries or you implement it yourself. All decoders must
-implement the `org.apache.activemq.artemis.utils.SensitiveDataCodec<T>`
-interface:
-
-``` java
-public interface SensitiveDataCodec<T>
-{
-   T decode(Object mask) throws Exception;
-
-   void init(Map<String, String> params);
-}
-```
-
-This is a generic type interface but normally for a password you just
-need String type. So a new decoder would be defined like
-
-```java
-public class MyNewDecoder implements SensitiveDataCodec<String>
-{
-   public String decode(Object mask) throws Exception
-   {
-      //decode the mask into clear text password
-      return "the password";
-   }
-
-   public void init(Map<String, String> params)
-   {
-      //initialization done here. It is called right after the decoder has 
been created.
-   }
-}
-```
-
-Last but not least, once you get your own decoder, please add it to the
-classpath. Otherwise Apache ActiveMQ Artemis will fail to load it!

http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/714655a0/docs/user-manual/en/masking-passwords.md
----------------------------------------------------------------------
diff --git a/docs/user-manual/en/masking-passwords.md 
b/docs/user-manual/en/masking-passwords.md
new file mode 100644
index 0000000..4f43524
--- /dev/null
+++ b/docs/user-manual/en/masking-passwords.md
@@ -0,0 +1,254 @@
+# Masking Passwords
+
+By default all passwords in Apache ActiveMQ Artemis server's configuration 
files are in
+plain text form. This usually poses no security issues as those files
+should be well protected from unauthorized accessing. However, in some
+circumstances a user doesn't want to expose its passwords to more eyes
+than necessary.
+
+Apache ActiveMQ Artemis can be configured to use 'masked' passwords in its
+configuration files. A masked password is an obscure string
+representation of a real password. To mask a password a user will use an
+'encoder'. The encoder takes in the real password and outputs the masked
+version. A user can then replace the real password in the configuration
+files with the new masked password. When Apache ActiveMQ Artemis loads a masked
+password, it uses a suitable 'decoder' to decode it into real password.
+
+Apache ActiveMQ Artemis provides a default password encoder and decoder. 
Optionally
+users can use or implement their own encoder and decoder for masking the
+passwords.
+
+### Password Masking in Server Configuration File
+
+#### General Masking Configuration
+
+The server configuration file (i.e. broker.xml )has a property that defines the
+default masking behaviors over the entire file scope.
+
+`mask-password`: this boolean type property indicates if a password
+should be masked or not. Set it to "true" if you want your passwords
+masked. The default value is "false".
+
+`password-codec`: this string type property identifies the name of the class
+which will be used to decode the masked password within the broker. If not
+specified then the default 
`org.apache.activemq.artemis.utils.DefaultSensitiveStringCodec`
+will be used.
+
+#### Specific Masking Behaviors
+
+##### cluster-password
+
+If `mask-password` is `true` the `cluster-password` will be treated as masked.
+
+##### Passwords in connectors and acceptors
+
+In broker.xml `connector` and `acceptor` configurations sometimes needs to
+specify passwords. For example, if a user wants to use an `acceptor` with
+`sslEnabled=true` it can specify `keyStorePassword` and `trustStorePassword`.
+Because Acceptors and Connectors are pluggable implementations, each transport
+will have different password masking needs.
+
+When a `connector` or `acceptor` is initialised, Apache ActiveMQ Artemis will
+add the aforementioned `mask-password` and `password-codec` values to the
+`connector` or `acceptor` parameters using the keys 
`activemq.usemaskedpassword`
+and `activemq.passwordcodec` respectively. The Netty and InVM implementations
+will use these as needed and any other implementations will have access to
+these to use if they so wish.
+
+##### Passwords in bridge configurations
+
+Core Bridges are configured in the server configuration file and so the
+masking of its `password` properties follows the same rules as that of
+`cluster-password`.
+
+#### Examples
+
+The following table summarizes the relations among the above-mentioned
+properties
+
+  mask-password  | cluster-password  | acceptor/connector passwords |  bridge 
password
+  :------------- | :---------------- | :--------------------------- | 
:---------------
+  absent   |       plain text     |    plain text       |              plain 
text
+  false    |       plain text     |    plain text       |              plain 
text
+  true     |       masked         |    masked           |              masked
+
+Examples
+
+Note: In the following examples if related attributed or properties are
+absent, it means they are not specified in the configure file.
+
+example 1
+
+```xml
+<cluster-password>bbc</cluster-password>
+```
+
+This indicates the cluster password is a plain text value ("bbc").
+
+example 2
+
+```xml
+<mask-password>true</mask-password>
+<cluster-password>80cf731af62c290</cluster-password>
+```
+
+This indicates the cluster password is a masked value and Apache ActiveMQ 
Artemis will
+use its built-in decoder to decode it. All other passwords in the
+configuration file, Connectors, Acceptors and Bridges, will also use
+masked passwords.
+
+### Masking passwords in ActiveMQ Artemis JCA ResourceAdapter and MDB 
activation configurations
+
+Both ra.xml and MDB activation configuration have a `password` property
+that can be masked. They are controlled by the following two optional
+Resource Adapter properties in ra.xml:
+
+`UseMaskedPassword` -- If setting to "true" the passwords are masked.
+Default is false.
+
+`PasswordCodec` -- Class name and its parameters for the Decoder used to
+decode the masked password. Ignored if UseMaskedPassword is false. The
+format of this property is a full qualified class name optionally
+followed by key/value pairs. It is the same format as that for JMS
+Bridges. Example:
+
+```xml
+<config-property>
+  <config-property-name>UseMaskedPassword</config-property-name>
+  <config-property-type>boolean</config-property-type>
+  <config-property-value>true</config-property-value>
+</config-property>
+<config-property>
+  <config-property-name>PasswordCodec</config-property-name>
+  <config-property-type>java.lang.String</config-property-type>
+  
<config-property-value>com.foo.ADecoder;key=helloworld</config-property-value>
+</config-property>
+```
+
+With this configuration, both passwords in ra.xml and all of its MDBs
+will have to be in masked form.
+
+### Masking passwords in artemis-users.properties
+
+Apache ActiveMQ Artemis's built-in security manager uses plain properties files
+where the user passwords are specified in a hashed form by default. Note, the 
passwords
+are technically *hashed* rather than masked in this context. The default 
`PropertiesLoginModule`
+will not decode the passwords in `artemis-users.properties` but will instead 
hash the input
+and compare the two hashed values for password verification.
+
+Please use Artemis CLI command to add a password. For example:
+
+```sh
+    ./artemis user add --username guest --password guest --role admin
+```
+
+This will use the default 
`org.apache.activemq.artemis.utils.DefaultSensitiveStringCodec`
+to perform a "one-way" hash of the password and alter both the 
`artemis-users.properties`
+and `artemis-roles.properties` files with the specified values.
+
+Passwords in `artemis-users.properties` are automatically detected as hashed 
or not
+by looking for the syntax `ENC(<hash>)`. The `mask-password` parameter does 
not need
+to be `true` to use hashed passwords here.
+
+### Choosing a decoder for password masking
+
+As described in the previous sections, all password masking requires a
+decoder. A decoder uses an algorithm to convert a masked password into
+its original clear text form in order to be used in various security
+operations. The algorithm used for decoding must match that for
+encoding. Otherwise the decoding may not be successful.
+
+For user's convenience Apache ActiveMQ Artemis provides a default decoder.
+However a user can implement their own if they wish.
+
+#### The Default Decoder
+
+Whenever no decoder is specified in the configuration file, the default
+decoder is used. The class name for the default decoder is
+`org.apache.activemq.artemis.utils.DefaultSensitiveStringCodec`. It has 
hashing,
+encoding, and decoding capabilities. It uses `java.crypto.Cipher` utilities
+to hash or encode a plaintext password and also to decode a masked string using
+same algorithm and key. Using this decoder/encoder is pretty straightforward. 
To
+get a mask for a password, just run the `mask` command:
+
+```sh
+./artemis mask <plaintextPassword>
+```
+
+You'll get something like
+
+```
+result: 32c6f67dae6cd61b0a7ad1702033aa81e6b2a760123f4360
+```
+
+Just copy `32c6f67dae6cd61b0a7ad1702033aa81e6b2a760123f4360` and replace your
+plaintext password in broker.xml with it.
+
+#### Using a custom decoder
+
+It is possible to use a custom decoder rather than the built-in one.
+Simply make sure the decoder is in Apache ActiveMQ Artemis's classpath. The 
custom decoder
+can also be service loaded rather than class loaded, if the decoder's service 
provider is installed in the classpath.
+Then configure the server to use it as follows:
+
+```xml
+    
<password-codec>com.foo.SomeDecoder;key1=value1;key2=value2</password-codec>
+```
+
+If your decoder needs params passed to it you can do this via key/value
+pairs when configuring. For instance if your decoder needs say a
+"key-location" parameter, you can define like so:
+
+```xml
+    
<password-codec>com.foo.NewDecoder;key-location=/some/url/to/keyfile</password-codec>
+```
+
+Then configure your cluster-password like this:
+
+```xml
+    <mask-password>true</mask-password>
+    <cluster-password>masked_password</cluster-password>
+```
+
+When Apache ActiveMQ Artemis reads the cluster-password it will initialize the
+NewDecoder and use it to decode "mask\_password". It also process all
+passwords using the new defined decoder.
+
+#### Implementing your own codecs
+
+To use a different decoder than the built-in one, you either pick one
+from existing libraries or you implement it yourself. All decoders must
+implement the `org.apache.activemq.artemis.utils.SensitiveDataCodec<T>`
+interface:
+
+``` java
+public interface SensitiveDataCodec<T>
+{
+   T decode(Object mask) throws Exception;
+
+   void init(Map<String, String> params);
+}
+```
+
+This is a generic type interface but normally for a password you just
+need String type. So a new decoder would be defined like
+
+```java
+public class MyNewDecoder implements SensitiveDataCodec<String>
+{
+   public String decode(Object mask) throws Exception
+   {
+      //decode the mask into clear text password
+      return "the password";
+   }
+
+   public void init(Map<String, String> params)
+   {
+      //initialization done here. It is called right after the decoder has 
been created.
+   }
+}
+```
+
+Last but not least, once you get your own decoder, please add it to the
+classpath by packaging it in a JAR file and putting the JAR file in the `lib`
+directory. Otherwise Apache ActiveMQ Artemis will fail to load it!
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/714655a0/docs/user-manual/en/security.md
----------------------------------------------------------------------
diff --git a/docs/user-manual/en/security.md b/docs/user-manual/en/security.md
index ef22e1f..91a3d33 100644
--- a/docs/user-manual/en/security.md
+++ b/docs/user-manual/en/security.md
@@ -427,6 +427,17 @@ the following:
     user=password
     guest=password
 
+Passwords in `artemis-users.properties` can be hashed. Such passwords should 
follow the syntax `ENC(<hash>)`. Hashed
+passwords can easily be added to `artemis-users.properties` using the `user` 
CLI command, e.g.:
+
+
+```sh
+    ./artemis user add --username guest --password guest --role admin
+```
+
+This will use the default 
`org.apache.activemq.artemis.utils.DefaultSensitiveStringCodec` to perform a 
"one-way" hash of
+the password and alter both the `artemis-users.properties` and 
`artemis-roles.properties` files with the specified values. 
+
 The `artemis-roles.properties` file consists of a list of properties of the 
form, `Role=UserList`, where UserList is a
 comma-separated list of users. For example, to define the roles `admins`, 
`users`, and `guests`, you could create a file
 like the following:
@@ -821,3 +832,7 @@ You need to put the black/white lists in its web.xml, as 
context parameters, as
     </web-app>
 
 The param-value for each list is a comma separated string value representing 
the list.
+
+## Masking Passwords
+
+For details about masking passwords in broker.xml please see the [Masking 
Passwords](masking-passwords.md) chapter.

Reply via email to