| <!DOCTYPE html> |
| <html lang="en"> |
| <head> |
| <meta charset="UTF-8"> |
| <meta http-equiv="X-UA-Compatible" content="IE=edge"> |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> |
| <meta name="generator" content="Asciidoctor 2.0.18"> |
| <link rel="icon" type="image/png" href="images/favicon.png"> |
| <title>Masking Passwords</title> |
| <link rel="stylesheet" href="css/asciidoctor.css"> |
| <link rel="stylesheet" href="css/font-awesome.css"> |
| <link rel="stylesheet" href="css/rouge-github.css"> |
| </head> |
| <body class="book toc2 toc-left"> |
| <div id="header"> |
| <h1>Masking Passwords</h1> |
| <div id="toc" class="toc2"> |
| <div id="toctitle"><a href="index.html">User Manual for 2.31.2</a></div> |
| <ul class="sectlevel1"> |
| <li><a href="#generating-a-masked-password">1. Generating a Masked Password</a></li> |
| <li><a href="#masking-configuration">2. Masking Configuration</a> |
| <ul class="sectlevel2"> |
| <li><a href="#artemis-users-properties">2.1. artemis-users.properties</a></li> |
| <li><a href="#cluster-password">2.2. cluster-password</a></li> |
| <li><a href="#connectors-acceptors">2.3. Connectors & Acceptors</a></li> |
| <li><a href="#core-bridges">2.4. Core Bridges</a></li> |
| <li><a href="#bootstrap-xml">2.5. bootstrap.xml</a></li> |
| <li><a href="#management-xml">2.6. management.xml</a></li> |
| <li><a href="#propertiesloginmodule">2.7. PropertiesLoginModule</a></li> |
| <li><a href="#ldaploginmodule">2.8. LDAPLoginModule</a></li> |
| <li><a href="#jca-resource-adapter">2.9. JCA Resource Adapter</a></li> |
| </ul> |
| </li> |
| <li><a href="#choosing-a-codec-for-password-masking">3. Choosing a codec for password masking</a> |
| <ul class="sectlevel2"> |
| <li><a href="#the-default-codec">3.1. The Default Codec</a></li> |
| <li><a href="#using-a-custom-codec">3.2. Using a custom codec</a></li> |
| </ul> |
| </li> |
| </ul> |
| </div> |
| </div> |
| <div id="content"> |
| <div id="preamble"> |
| <div class="sectionbody"> |
| <div class="paragraph"> |
| <p>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.</p> |
| </div> |
| <div class="paragraph"> |
| <p>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 '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 the codec to decode it back into the real password.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Apache ActiveMQ Artemis provides a default codec. |
| Optionally users can use or implement their own codec for masking the passwords.</p> |
| </div> |
| <div class="paragraph"> |
| <p>In general, a masked password can be identified using one of two ways. |
| The first one is the <code>ENC()</code> syntax, i.e. any string value wrapped in <code>ENC()</code> is to be treated as a masked password. |
| For example</p> |
| </div> |
| <div class="paragraph"> |
| <p><code>ENC(xyz)</code></p> |
| </div> |
| <div class="paragraph"> |
| <p>The above indicates that the password is masked and the masked value is <code>xyz</code>.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The <code>ENC()</code> syntax is the <strong>preferred way</strong> of masking a password and is universally supported in every password configuration in Artemis.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The other, legacy way is to use a <code>mask-password</code> attribute to tell that a password in a configuration file should be treated as 'masked'. |
| For example:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="rouge highlight nowrap"><code data-lang="xml"><span class="nt"><mask-password></span>true<span class="nt"></mask-password></span> |
| <span class="nt"><cluster-password></span>xyz<span class="nt"></cluster-password></span></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>This method is now <strong>deprecated</strong> and exists only to maintain backward-compatibility. |
| Newer configurations may not support it.</p> |
| </div> |
| </div> |
| </div> |
| <div class="sect1"> |
| <h2 id="generating-a-masked-password"><a class="anchor" href="#generating-a-masked-password"></a><a class="link" href="#generating-a-masked-password">1. Generating a Masked Password</a></h2> |
| <div class="sectionbody"> |
| <div class="paragraph"> |
| <p>To mask a password use the <code>mask</code> command from the <code>bin</code> directory of your Artemis <em>instance</em>. |
| This command will not work from the Artemis home.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The <code>mask</code> command uses <a href="#the-default-codec">the default codec</a> unless <a href="#using-a-custom-codec">a custom codec</a> is defined in <code>broker.xml</code> and the <code>--password-codec</code> option is <code>true</code>. |
| Here’s a simple example:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="rouge highlight nowrap"><code data-lang="sh">./artemis mask <plaintextPassword></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>You’ll get something like:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="nowrap">result: 32c6f67dae6cd61b0a7ad1702033aa81e6b2a760123f4360</pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Just copy <code>32c6f67dae6cd61b0a7ad1702033aa81e6b2a760123f4360</code> and replace your plaintext password with it using the <code>ENC()</code> syntax, e.g. <code>ENC(32c6f67dae6cd61b0a7ad1702033aa81e6b2a760123f4360)</code>.</p> |
| </div> |
| <div class="paragraph"> |
| <p>You can also use the <code>--key</code> parameter with the default codec. |
| Read more about <a href="#the-default-codec">the default codec</a> for further details about this parameter.</p> |
| </div> |
| <div class="paragraph"> |
| <p>This process works for passwords in:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p><code>broker.xml</code></p> |
| </li> |
| <li> |
| <p><code>login.config</code></p> |
| </li> |
| <li> |
| <p><code>bootstrap.xml</code></p> |
| </li> |
| <li> |
| <p><code>management.xml</code></p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>This process does <strong>not</strong> work for passwords in:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p><code>artemis-users.properties</code></p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>Masked passwords for <code>artemis-users.properties</code> <em>can</em> be generated using the <code>mask</code> command using the <code>--hash</code> command-line option. |
| However, this is also possible using the set of tools provided by the <code>user</code> command described below.</p> |
| </div> |
| </div> |
| </div> |
| <div class="sect1"> |
| <h2 id="masking-configuration"><a class="anchor" href="#masking-configuration"></a><a class="link" href="#masking-configuration">2. Masking Configuration</a></h2> |
| <div class="sectionbody"> |
| <div class="paragraph"> |
| <p>Besides supporting the <code>ENC()</code> syntax, the server configuration file (i.e. broker.xml) has a property that defines the default masking behaviors over the entire file scope.</p> |
| </div> |
| <div class="paragraph"> |
| <p><code>mask-password</code>: this boolean type property indicates if a password should be masked or not. |
| Set it to <code>true</code> if you want your passwords masked. |
| The default value is <code>false</code>. |
| As noted above, this configuration parameter is deprecated in favor of the <code>ENC()</code> syntax.</p> |
| </div> |
| <div class="paragraph"> |
| <p><code>password-codec</code>: 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 <code>org.apache.activemq.artemis.utils.DefaultSensitiveStringCodec</code> will be used. |
| Read more about <a href="#using-a-custom-codec">using a custom codec</a>.</p> |
| </div> |
| <div class="sect2"> |
| <h3 id="artemis-users-properties"><a class="anchor" href="#artemis-users-properties"></a><a class="link" href="#artemis-users-properties">2.1. artemis-users.properties</a></h3> |
| <div class="paragraph"> |
| <p>Apache ActiveMQ Artemis' default JAAS security manager uses plain properties files where the user passwords are specified in a hashed form by default. |
| Note, the passwords are technically <em>hashed</em> rather than masked in this context. |
| The default <code>PropertiesLoginModule</code> will not decode the passwords in <code>artemis-users.properties</code> but will instead hash the input and compare the two hashed values for password verification.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Use the following command from the CLI of the Artemis <em>instance</em> you wish to add the user/password to. |
| This command will not work from the Artemis home used to create the instance, and it will also not work unless the broker has been started. |
| For example:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="rouge highlight nowrap"><code data-lang="sh">./artemis user add <span class="nt">--user-command-user</span> guest <span class="nt">--user-command-password</span> guest <span class="nt">--role</span> admin</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>This will use the default codec to perform a "one-way" hash of the password and alter both the <code>artemis-users.properties</code> and <code>artemis-roles.properties</code> files with the specified values.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Passwords in <code>artemis-users.properties</code> are automatically detected as hashed or not by looking for the syntax <code>ENC(<hash>)</code>. |
| The <code>mask-password</code> parameter does not need to be <code>true</code> to use hashed passwords here.</p> |
| </div> |
| <div class="admonitionblock warning"> |
| <table> |
| <tr> |
| <td class="icon"> |
| <i class="fa icon-warning" title="Warning"></i> |
| </td> |
| <td class="content"> |
| <div class="paragraph"> |
| <p>Management and CLI operations to manipulate user & role data are only available when using the <code>PropertiesLoginModule</code>.</p> |
| </div> |
| <div class="paragraph"> |
| <p>In general, using properties files and broker-centric user management for anything other than very basic use-cases is not recommended. |
| The broker is designed to deal with messages. |
| It’s not in the business of managing users, although that functionality is provided at a limited level for convenience. |
| LDAP is recommended for enterprise level production use-cases.</p> |
| </div> |
| </td> |
| </tr> |
| </table> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="cluster-password"><a class="anchor" href="#cluster-password"></a><a class="link" href="#cluster-password">2.2. cluster-password</a></h3> |
| <div class="paragraph"> |
| <p>If it is specified in <code>ENC()</code> syntax it will be treated as masked, or if <code>mask-password</code> is <code>true</code> the <code>cluster-password</code> will be treated as masked.</p> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="connectors-acceptors"><a class="anchor" href="#connectors-acceptors"></a><a class="link" href="#connectors-acceptors">2.3. Connectors & Acceptors</a></h3> |
| <div class="paragraph"> |
| <p>In broker.xml <code>connector</code> and <code>acceptor</code> configurations sometimes needs to specify passwords. |
| For example, if a user wants to use an <code>acceptor</code> with <code>sslEnabled=true</code> it can specify <code>keyStorePassword</code> and <code>trustStorePassword</code>. |
| Because Acceptors and Connectors are pluggable implementations, each transport will have different password masking needs.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The preferred way is simply to use the <code>ENC()</code> syntax.</p> |
| </div> |
| <div class="paragraph"> |
| <p>If using the legacy <code>mask-password</code> and <code>password-codec</code> values then when a <code>connector</code> or <code>acceptor</code> is initialised, Apache ActiveMQ Artemis will add these values to the parameters using the keys <code>activemq.usemaskedpassword</code> and <code>activemq.passwordcodec</code> 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.</p> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="core-bridges"><a class="anchor" href="#core-bridges"></a><a class="link" href="#core-bridges">2.4. Core Bridges</a></h3> |
| <div class="paragraph"> |
| <p>Core Bridges are configured in the server configuration file and so the masking of its <code>password</code> properties follows the same rules as that of <code>cluster-password</code>. |
| It supports <code>ENC()</code> syntax.</p> |
| </div> |
| <div class="paragraph"> |
| <p>For using <code>mask-password</code> property, the following table summarizes the relations among the above-mentioned properties</p> |
| </div> |
| <table class="tableblock frame-all grid-all stretch"> |
| <colgroup> |
| <col style="width: 25%;"> |
| <col style="width: 25%;"> |
| <col style="width: 25%;"> |
| <col style="width: 25%;"> |
| </colgroup> |
| <thead> |
| <tr> |
| <th class="tableblock halign-left valign-top">mask-password</th> |
| <th class="tableblock halign-left valign-top">cluster-password</th> |
| <th class="tableblock halign-left valign-top">acceptor/connector passwords</th> |
| <th class="tableblock halign-left valign-top">bridge password</th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">absent</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">plain text</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">plain text</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">plain text</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">plain text</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">plain text</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">plain text</p></td> |
| </tr> |
| <tr> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">masked</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">masked</p></td> |
| <td class="tableblock halign-left valign-top"><p class="tableblock">masked</p></td> |
| </tr> |
| </tbody> |
| </table> |
| <div class="paragraph"> |
| <p>It is recommended that you use the <code>ENC()</code> syntax for new applications/deployments.</p> |
| </div> |
| <div class="sect3"> |
| <h4 id="examples"><a class="anchor" href="#examples"></a><a class="link" href="#examples">2.4.1. Examples</a></h4> |
| <div class="admonitionblock note"> |
| <table> |
| <tr> |
| <td class="icon"> |
| <i class="fa icon-note" title="Note"></i> |
| </td> |
| <td class="content"> |
| In the following examples if related attributed or properties are absent, it means they are not specified in the configure file. |
| </td> |
| </tr> |
| </table> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>Unmasked</p> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="rouge highlight nowrap"><code data-lang="xml"><span class="nt"><cluster-password></span>bbc<span class="nt"></cluster-password></span></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>This indicates the cluster password is a plain text value <code>bbc</code>.</p> |
| </div> |
| </li> |
| <li> |
| <p>Masked 1</p> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="rouge highlight nowrap"><code data-lang="xml"><span class="nt"><cluster-password></span>ENC(80cf731af62c290)<span class="nt"></cluster-password></span></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>This indicates the cluster password is a masked value <code>80cf731af62c290</code>.</p> |
| </div> |
| </li> |
| <li> |
| <p>Masked 2</p> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="rouge highlight nowrap"><code data-lang="xml"><span class="nt"><mask-password></span>true<span class="nt"></mask-password></span> |
| <span class="nt"><cluster-password></span>80cf731af62c290<span class="nt"></cluster-password></span></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>This indicates the cluster password is a masked value and Apache ActiveMQ Artemis will use <a href="#the-default-codec">the default codec</a> to decode it. |
| All other passwords in the configuration file, Connectors, Acceptors and Bridges, will also use masked passwords.</p> |
| </div> |
| </li> |
| </ul> |
| </div> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="bootstrap-xml"><a class="anchor" href="#bootstrap-xml"></a><a class="link" href="#bootstrap-xml">2.5. bootstrap.xml</a></h3> |
| <div class="paragraph"> |
| <p>The broker embeds a web-server for hosting some web applications such as a management console. |
| It is configured in <code>bootstrap.xml</code> as a web component. |
| The web server can be secured using the <code>https</code> protocol, and it can be configured with a keystore password and/or truststore password which by default are specified in plain text forms.</p> |
| </div> |
| <div class="paragraph"> |
| <p>To mask these passwords you need to use <code>ENC()</code> syntax. |
| The <code>mask-password</code> boolean is not supported here.</p> |
| </div> |
| <div class="paragraph"> |
| <p>You can also set the <code>passwordCodec</code> attribute if you want to use a password codec other than the default one. |
| For example</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="rouge highlight nowrap"><code data-lang="xml"><span class="nt"><web</span> <span class="na">path=</span><span class="s">"web"</span><span class="nt">></span> |
| <span class="nt"><binding</span> <span class="na">uri=</span><span class="s">"https://localhost:8443"</span> |
| <span class="na">keyStorePassword=</span><span class="s">"ENC(-5a2376c61c668aaf)"</span> |
| <span class="na">trustStorePassword=</span><span class="s">"ENC(3d617352d12839eb71208edf41d66b34)"</span><span class="nt">></span> |
| <span class="nt"><app</span> <span class="na">url=</span><span class="s">"activemq-branding"</span> <span class="na">war=</span><span class="s">"activemq-branding.war"</span><span class="nt">/></span> |
| <span class="nt"></binding></span> |
| <span class="nt"></web></span></code></pre> |
| </div> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="management-xml"><a class="anchor" href="#management-xml"></a><a class="link" href="#management-xml">2.6. management.xml</a></h3> |
| <div class="paragraph"> |
| <p>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 truststore password which by default are specified in plain text forms.</p> |
| </div> |
| <div class="paragraph"> |
| <p>To mask these passwords you need to use <code>ENC()</code> syntax. |
| The <code>mask-password</code> boolean is not supported here.</p> |
| </div> |
| <div class="paragraph"> |
| <p>You can also set the <code>password-codec</code> attribute if you want to use a password codec other than the default one. |
| For example</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="rouge highlight nowrap"><code data-lang="xml"><span class="nt"><connector</span> |
| <span class="na">connector-port=</span><span class="s">"1099"</span> |
| <span class="na">connector-host=</span><span class="s">"localhost"</span> |
| <span class="na">secured=</span><span class="s">"true"</span> |
| <span class="na">key-store-path=</span><span class="s">"myKeystore.jks"</span> |
| <span class="na">key-store-password=</span><span class="s">"ENC(3a34fd21b82bf2a822fa49a8d8fa115d"</span> |
| <span class="na">trust-store-path=</span><span class="s">"myTruststore.jks"</span> |
| <span class="na">trust-store-password=</span><span class="s">"ENC(3a34fd21b82bf2a822fa49a8d8fa115d)"</span><span class="nt">/></span></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>With this configuration, both passwords in ra.xml and all of its MDBs will have to be in masked form.</p> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="propertiesloginmodule"><a class="anchor" href="#propertiesloginmodule"></a><a class="link" href="#propertiesloginmodule">2.7. PropertiesLoginModule</a></h3> |
| <div class="paragraph"> |
| <p>Artemis supports Properties login module to be configured in JAAS configuration file (default name is <code>login.config</code>). |
| By default, the passwords of the users are in plain text or masked with the <a href="#the-default-codec">the default codec</a>.</p> |
| </div> |
| <div class="paragraph"> |
| <p>To use a custom codec class, set the <code>org.apache.activemq.jaas.properties.password.codec</code> property to the class name e.g. to use the <code>com.example.MySensitiveDataCodecImpl</code> codec class:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="nowrap">PropertiesLoginWithPasswordCodec { |
| org.apache.activemq.artemis.spi.core.security.jaas.PropertiesLoginModule required |
| debug=true |
| org.apache.activemq.jaas.properties.user="users.properties" |
| org.apache.activemq.jaas.properties.role="roles.properties" |
| org.apache.activemq.jaas.properties.password.codec="com.example.MySensitiveDataCodecImpl"; |
| };</pre> |
| </div> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="ldaploginmodule"><a class="anchor" href="#ldaploginmodule"></a><a class="link" href="#ldaploginmodule">2.8. LDAPLoginModule</a></h3> |
| <div class="paragraph"> |
| <p>Artemis supports LDAP login modules to be configured in JAAS configuration file (default name is <code>login.config</code>). |
| When connecting to an LDAP server usually you need to supply a connection password in the config file. |
| By default this password is in plain text form.</p> |
| </div> |
| <div class="paragraph"> |
| <p>To mask it you need to configure the passwords in your login module using <code>ENC()</code> syntax. |
| To specify a codec using the following property:</p> |
| </div> |
| <div class="paragraph"> |
| <p><code>passwordCodec</code> - the password codec class name. |
| (<a href="#the-default-codec">the default codec</a> will be used if it is absent)</p> |
| </div> |
| <div class="paragraph"> |
| <p>For example:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="nowrap">LDAPLoginExternalPasswordCodec { |
| 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(-170b9ef34d79ed12)" |
| passwordCodec="org.apache.activemq.artemis.utils.DefaultSensitiveStringCodec;key=helloworld" |
| connectionProtocol=s |
| authentication=simple |
| userBase="ou=system" |
| userSearchMatching="(uid={0})" |
| userSearchSubtree=false |
| roleBase="ou=system" |
| roleName=dummyRoleName |
| roleSearchMatching="(uid={1})" |
| roleSearchSubtree=false |
| ; |
| };</pre> |
| </div> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="jca-resource-adapter"><a class="anchor" href="#jca-resource-adapter"></a><a class="link" href="#jca-resource-adapter">2.9. JCA Resource Adapter</a></h3> |
| <div class="paragraph"> |
| <p>Both ra.xml and MDB activation configuration have a <code>password</code> property that can be masked preferably using <code>ENC()</code> syntax.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Alternatively it can use an optional attribute in ra.xml to indicate that a password is masked:</p> |
| </div> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1">UseMaskedPassword</dt> |
| <dd> |
| <p>If setting to "true" the passwords are masked. |
| Default is <code>false</code>.</p> |
| </dd> |
| </dl> |
| </div> |
| <div class="paragraph"> |
| <p>There is another property in <code>ra.xml</code> that can specify a codec:</p> |
| </div> |
| <div class="dlist"> |
| <dl> |
| <dt class="hdlist1">PasswordCodec</dt> |
| <dd> |
| <p>Class name and its parameters for the codec used to decode the masked password. |
| Ignored if <code>UseMaskedPassword</code> is <code>false</code>. |
| 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:</p> |
| </dd> |
| </dl> |
| </div> |
| <div class="paragraph"> |
| <p>Example 1 Using the <code>ENC()</code> syntax:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="rouge highlight nowrap"><code data-lang="xml"><span class="nt"><config-property></span> |
| <span class="nt"><config-property-name></span>password<span class="nt"></config-property-name></span> |
| <span class="nt"><config-property-type></span>String<span class="nt"></config-property-type></span> |
| <span class="nt"><config-property-value></span>ENC(80cf731af62c290)<span class="nt"></config-property-value></span> |
| <span class="nt"></config-property></span> |
| <span class="nt"><config-property></span> |
| <span class="nt"><config-property-name></span>PasswordCodec<span class="nt"></config-property-name></span> |
| <span class="nt"><config-property-type></span>java.lang.String<span class="nt"></config-property-type></span> |
| <span class="nt"><config-property-value></span>com.foo.ACodec;key=helloworld<span class="nt"></config-property-value></span> |
| <span class="nt"></config-property></span></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Example 2 Using the "UseMaskedPassword" property:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="rouge highlight nowrap"><code data-lang="xml"><span class="nt"><config-property></span> |
| <span class="nt"><config-property-name></span>UseMaskedPassword<span class="nt"></config-property-name></span> |
| <span class="nt"><config-property-type></span>boolean<span class="nt"></config-property-type></span> |
| <span class="nt"><config-property-value></span>true<span class="nt"></config-property-value></span> |
| <span class="nt"></config-property></span> |
| <span class="nt"><config-property></span> |
| <span class="nt"><config-property-name></span>password<span class="nt"></config-property-name></span> |
| <span class="nt"><config-property-type></span>String<span class="nt"></config-property-type></span> |
| <span class="nt"><config-property-value></span>80cf731af62c290<span class="nt"></config-property-value></span> |
| <span class="nt"></config-property></span> |
| <span class="nt"><config-property></span> |
| <span class="nt"><config-property-name></span>PasswordCodec<span class="nt"></config-property-name></span> |
| <span class="nt"><config-property-type></span>java.lang.String<span class="nt"></config-property-type></span> |
| <span class="nt"><config-property-value></span>com.foo.ACodec;key=helloworld<span class="nt"></config-property-value></span> |
| <span class="nt"></config-property></span></code></pre> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
| <div class="sect1"> |
| <h2 id="choosing-a-codec-for-password-masking"><a class="anchor" href="#choosing-a-codec-for-password-masking"></a><a class="link" href="#choosing-a-codec-for-password-masking">3. Choosing a codec for password masking</a></h2> |
| <div class="sectionbody"> |
| <div class="paragraph"> |
| <p>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.</p> |
| </div> |
| <div class="paragraph"> |
| <p>For user’s convenience Apache ActiveMQ Artemis provides a default codec. |
| However, a user can implement their own if they wish.</p> |
| </div> |
| <div class="sect2"> |
| <h3 id="the-default-codec"><a class="anchor" href="#the-default-codec"></a><a class="link" href="#the-default-codec">3.1. The Default Codec</a></h3> |
| <div class="paragraph"> |
| <p>Whenever no codec is specified in the configuration, the default codec is used. |
| The class name for the default codec is <code>org.apache.activemq.artemis.utils.DefaultSensitiveStringCodec</code>. |
| It has hashing, encoding, and decoding capabilities. |
| It uses <code>java.crypto.Cipher</code> utilities to hash or encode a plaintext password and also to decode a masked string using the same algorithm and "key."</p> |
| </div> |
| <div class="paragraph"> |
| <p>The "key" used here is important since the <em>same</em> key <strong>must</strong> be used to both mask and unmask the password. |
| The key is just a string of characters which the codec feeds to the underlying algorithm. |
| There is a default key in <code>org.apache.activemq.artemis.utils.DefaultSensitiveStringCodec</code>, but using the default key leaves open the possibility that nefarious actors could also use that key to unmask the password(s). |
| Therefore, it is possible to supply your <em>own</em> key, and there are a few ways to do this.</p> |
| </div> |
| <div class="olist arabic"> |
| <ol class="arabic"> |
| <li> |
| <p>Specify the key in the codec configuration using the <code>key=value</code> syntax. |
| Depending on which password you’re trying to mask the configuration specifics will differ slightly, but this can be done, for example, in <code>broker.xml</code> with <code><password-codec></code>:</p> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="rouge highlight nowrap"><code data-lang="xml"><span class="nt"><password-codec></span>org.apache.activemq.artemis.utils.DefaultSensitiveStringCodec;key=myKey<span class="nt"></password-codec></span></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Similar configurations are possible in any file that supports password masking, e.g. <code>boostrap.xml</code>, <code>login.config</code>, <code>management.xml</code>, etc. |
| The main drawback with this method is that the key will be stored in plain-text in the configuration file(s).</p> |
| </div> |
| </li> |
| <li> |
| <p>Set the system property -Dartemis.default.sensitive.string.codec.key=myKey.</p> |
| </li> |
| <li> |
| <p>Set the environment property <code>ARTEMIS_DEFAULT_SENSITIVE_STRING_CODEC_KEY</code>. |
| The benefit of using this method is that the key is more obscure since it will not exist in any configuration file. |
| It can be set immediately <em>before</em> the broker starts and then cleared from the environment immediately <em>after</em> the broker finishes starting.</p> |
| </li> |
| </ol> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="using-a-custom-codec"><a class="anchor" href="#using-a-custom-codec"></a><a class="link" href="#using-a-custom-codec">3.2. Using a custom codec</a></h3> |
| <div class="paragraph"> |
| <p>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:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="rouge highlight nowrap"><code data-lang="xml"><span class="nt"><password-codec></span>com.foo.SomeCodec;key1=value1;key2=value2<span class="nt"></password-codec></span></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>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:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="rouge highlight nowrap"><code data-lang="xml"><span class="nt"><password-codec></span>com.foo.NewCodec;key-location=/some/url/to/keyfile<span class="nt"></password-codec></span></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Then configure your cluster-password like this:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="rouge highlight nowrap"><code data-lang="xml"><span class="nt"><cluster-password></span>ENC(masked_password)<span class="nt"></cluster-password></span></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>When Apache ActiveMQ Artemis reads the cluster-password it will initialize the <code>NewCodec</code> and use it to decode "mask_password". |
| It also process all passwords using the new defined codec.</p> |
| </div> |
| <div class="sect3"> |
| <h4 id="implementing-custom-codecs"><a class="anchor" href="#implementing-custom-codecs"></a><a class="link" href="#implementing-custom-codecs">3.2.1. Implementing Custom Codecs</a></h4> |
| <div class="paragraph"> |
| <p>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 <code>org.apache.activemq.artemis.utils.SensitiveDataCodec<String></code> interface. |
| So a new codec would be defined like</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="rouge highlight nowrap"><code data-lang="java"><span class="kd">public</span> <span class="kd">class</span> <span class="nc">MyCodec</span> <span class="kd">implements</span> <span class="nc">SensitiveDataCodec</span><span class="o"><</span><span class="nc">String</span><span class="o">></span> <span class="o">{</span> |
| <span class="nd">@Override</span> |
| <span class="kd">public</span> <span class="nc">String</span> <span class="nf">decode</span><span class="o">(</span><span class="nc">Object</span> <span class="n">mask</span><span class="o">)</span> <span class="kd">throws</span> <span class="nc">Exception</span> <span class="o">{</span> |
| <span class="c1">// Decode the mask into clear text password.</span> |
| <span class="k">return</span> <span class="s">"the password"</span><span class="o">;</span> |
| <span class="o">}</span> |
| |
| <span class="nd">@Override</span> |
| <span class="kd">public</span> <span class="nc">String</span> <span class="nf">encode</span><span class="o">(</span><span class="nc">Object</span> <span class="n">secret</span><span class="o">)</span> <span class="kd">throws</span> <span class="nc">Exception</span> <span class="o">{</span> |
| <span class="c1">// Mask the clear text password.</span> |
| <span class="k">return</span> <span class="s">"the masked password"</span><span class="o">;</span> |
| <span class="o">}</span> |
| |
| <span class="nd">@Override</span> |
| <span class="kd">public</span> <span class="kt">void</span> <span class="nf">init</span><span class="o">(</span><span class="nc">Map</span><span class="o"><</span><span class="nc">String</span><span class="o">,</span> <span class="nc">String</span><span class="o">></span> <span class="n">params</span><span class="o">)</span> <span class="o">{</span> |
| <span class="c1">// Initialization done here. It is called right after the codec has been created.</span> |
| <span class="o">}</span> |
| |
| <span class="nd">@Override</span> |
| <span class="kd">public</span> <span class="kt">boolean</span> <span class="nf">verify</span><span class="o">(</span><span class="kt">char</span><span class="o">[]</span> <span class="n">value</span><span class="o">,</span> <span class="nc">String</span> <span class="n">encodedValue</span><span class="o">)</span> <span class="o">{</span> |
| <span class="c1">// Return true if the value matches the encodedValue.</span> |
| <span class="k">return</span> <span class="nf">checkValueMatchesEncoding</span><span class="o">(</span><span class="n">value</span><span class="o">,</span> <span class="n">encodedValue</span><span class="o">);</span> |
| <span class="o">}</span> |
| <span class="o">}</span></code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Last but not least, once you get your own codec please <a href="using-server.html#adding-runtime-dependencies">add it to the classpath</a> otherwise the broker will fail to load it!</p> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
| </body> |
| </html> |