ARTEMIS-2396 improve password masking doc
This commit is contained in:
parent
b394519f58
commit
d125a78841
|
@ -8,15 +8,14 @@ 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
|
||||
real password. To mask a password a user will use an 'codec'. The codec
|
||||
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.
|
||||
password. When Apache ActiveMQ Artemis loads a masked password it uses the
|
||||
codec to decode it back into the 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.
|
||||
Apache ActiveMQ Artemis provides a default codec. Optionally users can use
|
||||
or implement their own codec for masking the passwords.
|
||||
|
||||
In general, a masked password can be identified using one of two ways. The
|
||||
first one is the `ENC()` syntax, i.e. any string value wrapped in `ENC()` is to
|
||||
|
@ -29,8 +28,8 @@ The above indicates that the password is masked and the masked value is `xyz`.
|
|||
The `ENC()` syntax is the **preferred way** of masking a password and is
|
||||
universally supported in every password configuration in Artemis.
|
||||
|
||||
The other way is to use a `mask-password` attribute to tell that a password in
|
||||
a configuration file should be treated as 'masked'. For example:
|
||||
The other, legacy way is to use a `mask-password` attribute to tell that a
|
||||
password in a configuration file should be treated as 'masked'. For example:
|
||||
|
||||
```xml
|
||||
<mask-password>true</mask-password>
|
||||
|
@ -40,9 +39,42 @@ a configuration file should be treated as 'masked'. For example:
|
|||
This method is now **deprecated** and exists only to maintain
|
||||
backward-compatibility. Newer configurations may not support it.
|
||||
|
||||
### Password Masking in Server Configuration File
|
||||
## Generating a Masked Password
|
||||
|
||||
#### General Masking Configuration
|
||||
To get a mask for a password using the broker's default codec run the
|
||||
`mask` command from your Artemis *instance*. This command will not work
|
||||
from the Artemis home:
|
||||
|
||||
```sh
|
||||
./artemis mask <plaintextPassword>
|
||||
```
|
||||
|
||||
You'll get something like
|
||||
|
||||
```
|
||||
result: 32c6f67dae6cd61b0a7ad1702033aa81e6b2a760123f4360
|
||||
```
|
||||
|
||||
Just copy `32c6f67dae6cd61b0a7ad1702033aa81e6b2a760123f4360` and replace your
|
||||
plaintext password with it using the `ENC()` syntax, e.g.
|
||||
`ENC(32c6f67dae6cd61b0a7ad1702033aa81e6b2a760123f4360)`.
|
||||
|
||||
This process works for passwords in:
|
||||
|
||||
- `broker.xml`
|
||||
- `login.config`
|
||||
- `bootstrap.xml`
|
||||
- `management.xml`
|
||||
|
||||
This process does **not** work for passwords in:
|
||||
|
||||
- `artemis-users.properties`
|
||||
|
||||
Maksed passwords for `artemis-users.properties` *can* be generated using the
|
||||
`mask` command using the `--hash` command-line option. However, we recommend
|
||||
using the set of tools provided by the `user` command described below.
|
||||
|
||||
## Masking Configuration
|
||||
|
||||
Besides supporting the `ENC()` syntax, the server configuration file (i.e.
|
||||
broker.xml) has a property that defines the default masking behaviors over the
|
||||
|
@ -50,22 +82,44 @@ 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".
|
||||
value is "false". As noted above, this configuration parameter is deprecated.
|
||||
|
||||
`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
|
||||
### artemis-users.properties
|
||||
|
||||
##### cluster-password
|
||||
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.
|
||||
|
||||
Use the following command from the CLI of the Aremtis *instance* you wish to
|
||||
add the user/password to. This command will not work from the Artemis home
|
||||
used to create the instance. For example:
|
||||
|
||||
```sh
|
||||
./artemis user add --username guest --password guest --role admin
|
||||
```
|
||||
|
||||
This will use the default codec 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.
|
||||
|
||||
### cluster-password
|
||||
|
||||
If it is specified in `ENC()` syntax it will be treated as masked, or
|
||||
if `mask-password` is `true` the `cluster-password` will be treated as masked.
|
||||
|
||||
If `mask-password` is `true` the `cluster-password` will be treated as masked.
|
||||
|
||||
##### Connectors & Acceptors
|
||||
### Connectors & Acceptors
|
||||
|
||||
In broker.xml `connector` and `acceptor` configurations sometimes needs to
|
||||
specify passwords. For example, if a user wants to use an `acceptor` with
|
||||
|
@ -73,16 +127,16 @@ specify passwords. For example, if a user wants to use an `acceptor` with
|
|||
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.
|
||||
The preferred way is simply to use the `ENC()` syntax.
|
||||
|
||||
The preferred way, however, is to use the `ENC()` syntax.
|
||||
If using the legacy `mask-password` and `password-codec` values then when a
|
||||
`connector` or `acceptor` is initialised, Apache ActiveMQ Artemis will add
|
||||
these values to the 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.
|
||||
|
||||
##### Core Bridges
|
||||
### Core Bridges
|
||||
|
||||
Core Bridges are configured in the server configuration file and so the masking
|
||||
of its `password` properties follows the same rules as that of
|
||||
|
@ -97,8 +151,7 @@ absent|plain text|plain text|plain text
|
|||
false|plain text|plain text|plain text
|
||||
true|masked|masked|masked
|
||||
|
||||
It is recommended that you use the `ENC()` syntax for new
|
||||
applications/deployments.
|
||||
It is recommended that you use the `ENC()` syntax for new applications/deployments.
|
||||
|
||||
#### Examples
|
||||
|
||||
|
@ -116,10 +169,10 @@ absent, it means they are not specified in the configure file.
|
|||
- Masked 1
|
||||
|
||||
```xml
|
||||
<cluster-password>ENC(xyz)</cluster-password>
|
||||
<cluster-password>ENC(80cf731af62c290)</cluster-password>
|
||||
```
|
||||
|
||||
This indicates the cluster password is a masked value `xyz`.
|
||||
This indicates the cluster password is a masked value `80cf731af62c290`.
|
||||
|
||||
- Masked 2
|
||||
|
||||
|
@ -129,17 +182,17 @@ absent, it means they are not specified in the configure file.
|
|||
```
|
||||
|
||||
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
|
||||
Artemis will use its built-in codec to decode it. All other passwords in the
|
||||
configuration file, Connectors, Acceptors and Bridges, will also use masked
|
||||
passwords.
|
||||
|
||||
#### Passwords in bootstrap.xml
|
||||
### bootstrap.xml
|
||||
|
||||
The broker embeds a web-server for hosting some web applications such as a
|
||||
management console. It is configured in bootstrap.xml as a web component. The
|
||||
web server can be secured using https protocol, and it can be configured with a
|
||||
keystore password and/or truststore password which by default are specified in
|
||||
plain text forms.
|
||||
management console. It is configured in `bootstrap.xml` as a web component. The
|
||||
web server can be secured using the `https` protocol, and it can be configured
|
||||
with a keystore password and/or truststore password which by default are
|
||||
specified in plain text forms.
|
||||
|
||||
To mask these passwords you need to use `ENC()` syntax. The `mask-password`
|
||||
boolean is not supported here.
|
||||
|
@ -155,7 +208,7 @@ codec other than the default one. For example
|
|||
</web>
|
||||
```
|
||||
|
||||
#### Passwords in management.xml
|
||||
### management.xml
|
||||
|
||||
The broker embeds a JMX connector which is used for management. The connector can
|
||||
be secured using SSL and it can be configured with a keystore password and/or
|
||||
|
@ -178,87 +231,10 @@ codec other than the default one. For example
|
|||
trust-store-password="ENC(3a34fd21b82bf2a822fa49a8d8fa115d)"/>
|
||||
```
|
||||
|
||||
### Passwords for the JCA Resource Adapter
|
||||
|
||||
Both ra.xml and MDB activation configuration have a `password` property that
|
||||
can be masked preferably using `ENC()` syntax.
|
||||
|
||||
Alternatively it can use an optional attribute in ra.xml to indicate that a
|
||||
password is masked:
|
||||
|
||||
`UseMaskedPassword` -- If setting to "true" the passwords are masked. Default
|
||||
is false.
|
||||
|
||||
There is another property in ra.xml that can specify a codec:
|
||||
|
||||
`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:
|
||||
|
||||
Example 1 Using the `ENC()` syntax:
|
||||
|
||||
```xml
|
||||
<config-property>
|
||||
<config-property-name>password</config-property-name>
|
||||
<config-property-type>String</config-property-type>
|
||||
<config-property-value>ENC(xyz)</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>
|
||||
```
|
||||
|
||||
Example 2 Using the "UseMaskedPassword" property:
|
||||
|
||||
```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>password</config-property-name>
|
||||
<config-property-type>String</config-property-type>
|
||||
<config-property-value>xyz</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.
|
||||
|
||||
### 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.
|
||||
|
||||
### Password in login.config
|
||||
### login.config
|
||||
|
||||
Artemis supports LDAP login modules to be configured in JAAS configuration file
|
||||
(default name is `login.config`). When connecting to a LDAP server usually you
|
||||
|
@ -295,58 +271,97 @@ LDAPLoginExternalPasswordCodec {
|
|||
};
|
||||
```
|
||||
|
||||
### Choosing a decoder for password masking
|
||||
### JCA Resource Adapter
|
||||
|
||||
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
|
||||
Both ra.xml and MDB activation configuration have a `password` property that
|
||||
can be masked preferably using `ENC()` syntax.
|
||||
|
||||
Alternatively it can use an optional attribute in ra.xml to indicate that a
|
||||
password is masked:
|
||||
|
||||
`UseMaskedPassword` -- If setting to "true" the passwords are masked. Default
|
||||
is false.
|
||||
|
||||
There is another property in ra.xml that can specify a codec:
|
||||
|
||||
`PasswordCodec` -- Class name and its parameters for the codec 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:
|
||||
|
||||
Example 1 Using the `ENC()` syntax:
|
||||
|
||||
```xml
|
||||
<config-property>
|
||||
<config-property-name>password</config-property-name>
|
||||
<config-property-type>String</config-property-type>
|
||||
<config-property-value>ENC(80cf731af62c290)</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.ACodec;key=helloworld</config-property-value>
|
||||
</config-property>
|
||||
```
|
||||
|
||||
Example 2 Using the "UseMaskedPassword" property:
|
||||
|
||||
```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>password</config-property-name>
|
||||
<config-property-type>String</config-property-type>
|
||||
<config-property-value>80cf731af62c290</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.ACodec;key=helloworld</config-property-value>
|
||||
</config-property>
|
||||
```
|
||||
|
||||
## Choosing a codec for password masking
|
||||
|
||||
As described in the previous sections, all password masking requires a codec.
|
||||
A codec 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.
|
||||
For user's convenience Apache ActiveMQ Artemis provides a default codec.
|
||||
However a user can implement their own if they wish.
|
||||
|
||||
#### The Default Decoder
|
||||
### The Default Codec
|
||||
|
||||
Whenever no decoder is specified in the configuration file, the default decoder
|
||||
is used. The class name for the default decoder is
|
||||
Whenever no codec is specified in the configuration, the default codec
|
||||
is used. The class name for the default codec 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:
|
||||
string using the same algorithm and key.
|
||||
|
||||
```sh
|
||||
./artemis mask <plaintextPassword>
|
||||
```
|
||||
### Using a custom codec
|
||||
|
||||
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
|
||||
It is possible to use a custom codec rather than the built-in one. Simply
|
||||
make sure the codec is in Apache ActiveMQ Artemis's classpath. The custom
|
||||
codec can also be service loaded rather than class loaded, if the codec'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>
|
||||
<password-codec>com.foo.SomeCodec;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"
|
||||
If your codec needs params passed to it you can do this via key/value pairs
|
||||
when configuring. For instance if your codec 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>
|
||||
<password-codec>com.foo.NewCodec;key-location=/some/url/to/keyfile</password-codec>
|
||||
```
|
||||
|
||||
Then configure your cluster-password like this:
|
||||
|
@ -356,43 +371,51 @@ Then configure your cluster-password like this:
|
|||
```
|
||||
|
||||
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.
|
||||
`NewCodec` and use it to decode "mask\_password". It also process all passwords
|
||||
using the new defined codec.
|
||||
|
||||
#### Implementing Custom 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
|
||||
To use a different codec than the built-in one, you either pick one from
|
||||
existing libraries or you implement it yourself. All codecs must implement
|
||||
the `org.apache.activemq.artemis.utils.SensitiveDataCodec<T>` interface:
|
||||
|
||||
```java
|
||||
public interface SensitiveDataCodec<T>
|
||||
{
|
||||
public interface SensitiveDataCodec<T> {
|
||||
|
||||
T decode(Object mask) throws Exception;
|
||||
|
||||
void init(Map<String, String> params);
|
||||
T encode(Object secret) throws Exception;
|
||||
|
||||
default void init(Map<String, String> params) throws Exception {
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
This is a generic type interface but normally for a password you just need
|
||||
String type. So a new decoder would be defined like
|
||||
String type. So a new codec 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
|
||||
public class MyCodec implements SensitiveDataCodec<String> {
|
||||
@Override
|
||||
public String decode(Object mask) throws Exception {
|
||||
// Decode the mask into clear text password.
|
||||
return "the password";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String encode(Object secret) throws Exception {
|
||||
// Mask the clear text password.
|
||||
return "the masked password"";
|
||||
}
|
||||
|
||||
public void init(Map<String, String> params)
|
||||
{
|
||||
//initialization done here. It is called right after the decoder has been created.
|
||||
@Override
|
||||
public void init(Map<String, String> params) {
|
||||
// Initialization done here. It is called right after the codec has been created.
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Last but not least, once you get your own decoder please [add it to the
|
||||
Last but not least, once you get your own codec please [add it to the
|
||||
classpath](using-server.md#adding-runtime-dependencies) otherwise the broker
|
||||
will fail to load it!
|
||||
|
|
|
@ -524,16 +524,16 @@ 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.:
|
||||
`artemis-users.properties` using the `user` CLI command from the Artemis
|
||||
*instance*. This command will not work from the Artemis home.
|
||||
|
||||
```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.
|
||||
This will use the default codec 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
|
||||
|
|
Loading…
Reference in New Issue