activemq-artemis/docs/user-manual/en/security.md

781 lines
43 KiB
Markdown

# Security
This chapter describes how security works with Apache ActiveMQ Artemis and how you can
configure it. To disable security completely simply set the
`security-enabled` property to false in the `broker.xml`
file.
For performance reasons security is cached and invalidated every so
long. To change this period set the property
`security-invalidation-interval`, which is in milliseconds. The default
is `10000` ms.
To assist in security auditing the `populate-validated-user` option exists. If this is `true` then
the server will add the name of the validated user to the message using the key `_AMQ_VALIDATED_USER`.
For JMS and Stomp clients this is mapped to the key `JMSXUserID`. For users authenticated based on
their SSL certificate this name is the name to which their certificate's DN maps. If `security-enabled`
is `false` and `populate-validated-user` is `true` then the server will simply use whatever user name
(if any) the client provides. This option is `false` by default.
## Role based security for addresses
Apache ActiveMQ Artemis contains a flexible role-based security model for applying
security to queues, based on their addresses.
As explained in [Using Core](using-core.md), Apache ActiveMQ Artemis core consists mainly of sets of queues bound
to addresses. A message is sent to an address and the server looks up
the set of queues that are bound to that address, the server then routes
the message to those set of queues.
Apache ActiveMQ Artemis allows sets of permissions to be defined against the queues
based on their address. An exact match on the address can be used or a
wildcard match can be used using the wildcard characters '`#`' and
'`*`'.
Seven different permissions can be given to the set of queues which
match the address. Those permissions are:
- `createDurableQueue`. This permission allows the user to create a
durable queue under matching addresses.
- `deleteDurableQueue`. This permission allows the user to delete a
durable queue under matching addresses.
- `createNonDurableQueue`. This permission allows the user to create a
non-durable queue under matching addresses.
- `deleteNonDurableQueue`. This permission allows the user to delete a
non-durable queue under matching addresses.
- `send`. This permission allows the user to send a message to
matching addresses.
- `consume`. This permission allows the user to consume a message from
a queue bound to matching addresses.
- `browse`. This permission allows the user to browse a queue bound to
the matching address.
- `manage`. This permission allows the user to invoke management
operations by sending management messages to the management address.
For each permission, a list of roles who are granted that permission is
specified. If the user has any of those roles, he/she will be granted
that permission for that set of addresses.
Let's take a simple example, here's a security block from
`broker.xml` file:
<security-setting match="globalqueues.europe.#">
<permission type="createDurableQueue" roles="admin"/>
<permission type="deleteDurableQueue" roles="admin"/>
<permission type="createNonDurableQueue" roles="admin, guest, europe-users"/>
<permission type="deleteNonDurableQueue" roles="admin, guest, europe-users"/>
<permission type="send" roles="admin, europe-users"/>
<permission type="consume" roles="admin, europe-users"/>
</security-setting>
The '`#`' character signifies "any sequence of words". Words are
delimited by the '`.`' character. For a full description of the wildcard
syntax please see [Understanding the Wildcard Syntax](wildcard-syntax.md).
The above security block applies to any address
that starts with the string "globalqueues.europe.":
Only users who have the `admin` role can create or delete durable queues
bound to an address that starts with the string "globalqueues.europe."
Any users with the roles `admin`, `guest`, or `europe-users` can create
or delete temporary queues bound to an address that starts with the
string "globalqueues.europe."
Any users with the roles `admin` or `europe-users` can send messages to
these addresses or consume messages from queues bound to an address that
starts with the string "globalqueues.europe."
The mapping between a user and what roles they have is handled by the
security manager. Apache ActiveMQ Artemis ships with a user manager that reads user
credentials from a file on disk, and can also plug into JAAS or JBoss
Application Server security.
For more information on configuring the security manager, please see 'Changing the Security Manager'.
There can be zero or more `security-setting` elements in each xml file.
Where more than one match applies to a set of addresses the *more
specific* match takes precedence.
Let's look at an example of that, here's another `security-setting`
block:
<security-setting match="globalqueues.europe.orders.#">
<permission type="send" roles="europe-users"/>
<permission type="consume" roles="europe-users"/>
</security-setting>
In this `security-setting` block the match
'globalqueues.europe.orders.\#' is more specific than the previous match
'globalqueues.europe.\#'. So any addresses which match
'globalqueues.europe.orders.\#' will take their security settings *only*
from the latter security-setting block.
Note that settings are not inherited from the former block. All the
settings will be taken from the more specific matching block, so for the
address 'globalqueues.europe.orders.plastics' the only permissions that
exist are `send` and `consume` for the role europe-users. The
permissions `createDurableQueue`, `deleteDurableQueue`,
`createNonDurableQueue`, `deleteNonDurableQueue` are not inherited from
the other security-setting block.
By not inheriting permissions, it allows you to effectively deny
permissions in more specific security-setting blocks by simply not
specifying them. Otherwise it would not be possible to deny permissions
in sub-groups of addresses.
## Security Setting Plugin
Aside from configuring sets of permissions via XML these permissions can alternatively be
configured via a plugin which implements `org.apache.activemq.artemis.core.server.SecuritySettingPlugin` e.g.:
<security-settings>
<security-setting-plugin class-name="org.apache.activemq.artemis.core.server.impl.LegacyLDAPSecuritySettingPlugin">
<setting name="initialContextFactory" value="com.sun.jndi.ldap.LdapCtxFactory"/>
<setting name="connectionURL" value="ldap://localhost:1024"/>
<setting name="connectionUsername" value="uid=admin,ou=system"/>
<setting name="connectionPassword" value="secret"/>
<setting name="connectionProtocol" value="s"/>
<setting name="authentication" value="simple"/>
</security-setting-plugin>
</security-settings>
Most of this configuration is specific to the plugin implementation. However, there are two configuration details that
will be specified for every implementation:
- `class-name`. This attribute of `security-setting-plugin` indicates the name of the class which implements
`org.apache.activemq.artemis.core.server.SecuritySettingPlugin`.
- `setting`. Each of these elements represents a name/value pair that will be passed to the implementation for configuration
purposes.
See the JavaDoc on `org.apache.activemq.artemis.core.server.SecuritySettingPlugin` for further details about the interface
and what each method is expected to do.
### Available plugins
#### LegacyLDAPSecuritySettingPlugin
This plugin will read the security information that was previously handled by [`LDAPAuthorizationMap`](http://activemq.apache.org/security.html)
and the [`cachedLDAPAuthorizationMap`](http://activemq.apache.org/cached-ldap-authorization-module.html) in Apache ActiveMQ 5.x
and turn it into Artemis security settings where possible. The security implementations of ActiveMQ 5.x and Artemis don't
match perfectly so some translation must occur to achieve near equivalent functionality.
Here is an example of the plugin's configuration:
<security-setting-plugin class-name="org.apache.activemq.artemis.core.server.impl.LegacyLDAPSecuritySettingPlugin">
<setting name="initialContextFactory" value="com.sun.jndi.ldap.LdapCtxFactory"/>
<setting name="connectionURL" value="ldap://localhost:1024"/>
<setting name="connectionUsername" value="uid=admin,ou=system"/>
<setting name="connectionPassword" value="secret"/>
<setting name="connectionProtocol" value="s"/>
<setting name="authentication" value="simple"/>
</security-setting-plugin>
- `class-name`. The implementation is `org.apache.activemq.artemis.core.server.impl.LegacyLDAPSecuritySettingPlugin`.
- `initialContextFactory`. The initial context factory used to connect to LDAP. It must always be set to
`com.sun.jndi.ldap.LdapCtxFactory` (i.e. the default value).
- `connectionURL`. Specifies the location of the directory server using an ldap URL, `ldap://Host:Port`. You can
optionally qualify this URL, by adding a forward slash, `/`, followed by the DN of a particular node in the directory
tree. For example, `ldap://ldapserver:10389/ou=system`. The default is `ldap://localhost:1024`.
- `connectionUsername`. The DN of the user that opens the connection to the directory server. For example, `uid=admin,ou=system`.
Directory servers generally require clients to present username/password credentials in order to open a connection.
- `connectionPassword`. The password that matches the DN from `connectionUsername`. In the directory server, in the
DIT, the password is normally stored as a `userPassword` attribute in the corresponding directory entry.
- `connectionProtocol`. Currently the only supported value is a blank string. In future, this option will allow you to
select the Secure Socket Layer (SSL) for the connection to the directory server. Note: this option must be set
explicitly to an empty string, because it has no default value.
- `authentication`. Specifies the authentication method used when binding to the LDAP server. Can take either of the
values, `simple` (username and password, the default value) or `none` (anonymous). Note: Simple Authentication and
Security Layer (SASL) authentication is currently not supported.
- `destinationBase`. Specifies the DN of the node whose children provide the permissions for all destinations. In this
case the DN is a literal value (that is, no string substitution is performed on the property value). For example, a
typical value of this property is `ou=destinations,o=ActiveMQ,ou=system` (i.e. the default value).
- `filter`. Specifies an LDAP search filter, which is used when looking up the permissions for any kind of destination.
The search filter attempts to match one of the children or descendants of the queue or topic node. The default value
is `(cn=*)`.
- `roleAttribute`. Specifies an attribute of the node matched by `filter`, whose value is the DN of a role. Default
value is `uniqueMember`.
- `adminPermissionValue`. Specifies a value that matches the `admin` permission. The default value is `admin`.
- `readPermissionValue`. Specifies a value that matches the `read` permission. The default value is `read`.
- `writePermissionValue`. Specifies a value that matches the `write` permission. The default value is `write`.
- `enableListener`. Whether or not to enable a listener that will automatically receive updates made in the LDAP server
and update the broker's authorization configuration in real-time. The default value is `true`.
The name of the queue or topic defined in LDAP will serve as the "match" for the security-setting, the permission value
will be mapped from the ActiveMQ 5.x type to the Artemis type, and the role will be mapped as-is. It's worth noting that
since the name of queue or topic coming from LDAP will server as the "match" for the security-setting the security-setting
may not be applied as expected to JMS destinations since Artemis always prefixes JMS destinations with "jms.queue." or
"jms.topic." as necessary.
ActiveMQ 5.x only has 3 permission types - `read`, `write`, and `admin`. These permission types are described on their
[website](http://activemq.apache.org/security.html). However, as described previously, ActiveMQ Artemis has 7 permission
types - `createDurableQueue`, `deleteDurableQueue`, `createNonDurableQueue`, `deleteNonDurableQueue`, `send`, `consume`,
`browse`, and `manage`. Here's how the old types are mapped to the new types:
- `read` - `consume`, `browse`
- `write` - `send`
- `admin` - `createDurableQueue`, `deleteDurableQueue`, `createNonDurableQueue`, `deleteNonDurableQueue`
As mentioned, there are a few places where a translation was performed to achieve some equivalence.:
- This mapping doesn't include the Artemis `manage` permission type since there is no type analogous for that in ActiveMQ
5.x.
- The `admin` permission in ActiveMQ 5.x relates to whether or not the broker will auto-create a destination if
it doesn't exist and the user sends a message to it. Artemis automatically allows the automatic creation of a
destination if the user has permission to send message to it. Therefore, the plugin will map the `admin` permission
to the 4 aforementioned permissions in Artemis.
## Secure Sockets Layer (SSL) Transport
When messaging clients are connected to servers, or servers are connected to other servers (e.g. via bridges) over an
untrusted network then Apache ActiveMQ Artemis allows that traffic to be encrypted using the Secure Sockets Layer (SSL)
transport.
For more information on configuring the SSL transport, please see [Configuring the Transport](configuring-transports.md).
## User credentials
Apache ActiveMQ Artemis ships with two security manager implementations:
- The legacy, deprecated `ActiveMQSecurityManager` that reads user credentials, i.e. user names, passwords and role
information from properties files on the classpath called `artemis-users.properties` and `artemis-roles.properties`.
- The flexible, pluggable `ActiveMQJAASSecurityManager` which supports any standard JAAS login module. Artemis ships
with several login modules which will be discussed further down. This is the default security manager.
### JAAS Security Manager
When using JAAS much of the configuration depends on which login module is used. However, there are a few commonalities
for every case. The first place to look is in `bootstrap.xml`. Here is an example using the `PropertiesLogin` JAAS login
module which reads user, password, and role information from properties files:
<jaas-security domain="PropertiesLogin"/>
No matter what login module you're using, you'll need to specify it here in `bootstrap.xml`. The `domain` attribute
here refers to the relevant login module entry in `login.config`. For example:
PropertiesLogin {
org.apache.activemq.artemis.spi.core.security.jaas.PropertiesLoginModule required
debug=true
org.apache.activemq.jaas.properties.user="artemis-users.properties"
org.apache.activemq.jaas.properties.role="artemis-roles.properties";
};
The `login.config` file is a standard JAAS configuration file. You can read more about this file on
[Oracle's website](https://docs.oracle.com/javase/8/docs/technotes/guides/security/jgss/tutorials/LoginConfigFile.html).
In short, the file defines:
- an alias for an entry (e.g. `PropertiesLogin`)
- the implementation class for the login module (e.g. `org.apache.activemq.artemis.spi.core.security.jaas.PropertiesLoginModule`)
- a flag which indicates whether the success of the login module is `required`, `requisite`, `sufficient`, or `optional`
(see more details on these flags in the [JavaDoc](http://docs.oracle.com/javase/8/docs/api/javax/security/auth/login/Configuration.html)
- a list of configuration options specific to the login module implementation
By default, the location and name of `login.config` is specified on the Artemis command-line which is set by
`etc/artemis.profile` on linux and `etc\artemis.profile.cmd` on Windows.
#### Dual Authentication
The JAAS Security Manager also supports another configuration parameter - `certificate-domain`. This is useful when you
want to authenticate clients connecting with SSL connections based on their SSL certificates (e.g. using the `CertificateLoginModule`
discussed below) but you still want to authenticate clients connecting with non-SSL connections with, e.g., username and
password. Here's an example of what would go in `bootstrap.xml`:
<jaas-security domain="PropertiesLogin" certificate-domain="CertLogin"/>
And here's the corresponding `login.config`:
PropertiesLogin {
org.apache.activemq.artemis.spi.core.security.jaas.PropertiesLoginModule required
debug=false
org.apache.activemq.jaas.properties.user="artemis-users.properties"
org.apache.activemq.jaas.properties.role="artemis-roles.properties";
};
CertLogin {
org.apache.activemq.artemis.spi.core.security.jaas.TextFileCertificateLoginModule required
debug=true
org.apache.activemq.jaas.textfiledn.user="cert-users.properties"
org.apache.activemq.jaas.textfiledn.role="cert-roles.properties";
};
When the broker is configured this way then any client connecting with SSL and a client certificate will be authenticated
using `CertLogin` and any client connecting without SSL will be authenticated using `PropertiesLogin`.
### JAAS Login Modules
#### GuestLoginModule
Allows users without credentials (and, depending on how it is configured, possibly also users with invalid credentials)
to access the broker. Normally, the guest login module is chained with another login module, such as a properties login
module. It is implemented by `org.apache.activemq.artemis.spi.core.security.jaas.GuestLoginModule`.
- `org.apache.activemq.jaas.guest.user` - the user name to assign; default is "guest"
- `org.apache.activemq.jaas.guest.role` - the role name to assign; default is "guests"
- `credentialsInvalidate` - boolean flag; if `true`, reject login requests that include a password (i.e. guest login
succeeds only when the user does not provide a password); default is `false`
- `debug` - boolean flag; if `true`, enable debugging; this is used only for testing or debugging; normally, it
should be set to `false`, or omitted; default is `false`
There are two basic use cases for the guest login module, as follows:
- Guests with no credentials or invalid credentials.
- Guests with no credentials only.
The following snippet shows how to configure a JAAS login entry for the use case where users with no credentials or
invalid credentials are logged in as guests. In this example, the guest login module is used in combination with the
properties login module.
activemq-domain {
org.apache.activemq.artemis.spi.core.security.jaas.PropertiesLoginModule sufficient
debug=true
org.apache.activemq.jaas.properties.user="artemis-users.properties"
org.apache.activemq.jaas.properties.role="artemis-roles.properties";
org.apache.activemq.artemis.spi.core.security.jaas.GuestLoginModule sufficient
debug=true
org.apache.activemq.jaas.guest.user="anyone"
org.apache.activemq.jaas.guest.role="restricted";
};
Depending on the user login data, authentication proceeds as follows:
- User logs in with a valid password — the properties login module successfully authenticates the user and returns
immediately. The guest login module is not invoked.
- User logs in with an invalid password — the properties login module fails to authenticate the user, and authentication
proceeds to the guest login module. The guest login module successfully authenticates the user and returns the guest principal.
- User logs in with a blank password — the properties login module fails to authenticate the user, and authentication
proceeds to the guest login module. The guest login module successfully authenticates the user and returns the guest principal.
The following snipped shows how to configure a JAAS login entry for the use case where only those users with no
credentials are logged in as guests. To support this use case, you must set the credentialsInvalidate option to true in
the configuration of the guest login module. You should also note that, compared with the preceding example, the order
of the login modules is reversed and the flag attached to the properties login module is changed to requisite.
activemq-guest-when-no-creds-only-domain {
org.apache.activemq.artemis.spi.core.security.jaas.GuestLoginModule sufficient
debug=true
credentialsInvalidate=true
org.apache.activemq.jaas.guest.user="guest"
org.apache.activemq.jaas.guest.role="guests";
org.apache.activemq.artemis.spi.core.security.jaas.PropertiesLoginModule requisite
debug=true
org.apache.activemq.jaas.properties.user="artemis-users.properties"
org.apache.activemq.jaas.properties.role="artemis-roles.properties";
};
Depending on the user login data, authentication proceeds as follows:
- User logs in with a valid password — the guest login module fails to authenticate the user (because the user has
presented a password while the credentialsInvalidate option is enabled) and authentication proceeds to the properties
login module. The properties login module successfully authenticates the user and returns.
- User logs in with an invalid password — the guest login module fails to authenticate the user and authentication proceeds
to the properties login module. The properties login module also fails to authenticate the user. The nett result is
authentication failure.
- User logs in with a blank password — the guest login module successfully authenticates the user and returns immediately.
The properties login module is not invoked.
#### PropertiesLoginModule
The JAAS properties login module provides a simple store of authentication data, where the relevant user data is stored
in a pair of flat files. This is convenient for demonstrations and testing, but for an enterprise system, the integration
with LDAP is preferable. It is implemented by `org.apache.activemq.artemis.spi.core.security.jaas.PropertiesLoginModule`.
- `org.apache.activemq.jaas.properties.user` - the path to the file which contains user and password properties
- `org.apache.activemq.jaas.properties.role` - the path to the file which contains user and role properties
- `reload` - boolean flag; whether or not to reload the properties files when a modification occurs; default is `false`
- `debug` - boolean flag; if `true`, enable debugging; this is used only for testing or debugging; normally, it
should be set to `false`, or omitted; default is `false`
In the context of the properties login module, the `artemis-users.properties` file consists of a list of properties of the
form, `UserName=Password`. For example, to define the users `system`, `user`, and `guest`, you could create a file like
the following:
system=manager
user=password
guest=password
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:
admins=system
users=system,user
guests=guest
#### LDAPLoginModule
The LDAP login module enables you to perform authentication and authorization by checking the incoming credentials against
user data stored in a central X.500 directory server. For systems that already have an X.500 directory server in place,
this means that you can rapidly integrate ActiveMQ Artemis with the existing security database and user accounts can be
managed using the X.500 system. It is implemented by `org.apache.activemq.artemis.spi.core.security.jaas.LDAPLoginModule`.
- `initialContextFactory` - must always be set to `com.sun.jndi.ldap.LdapCtxFactory`
- `connectionURL` - specify the location of the directory server using an ldap URL, ldap://Host:Port. You can
optionally qualify this URL, by adding a forward slash, `/`, followed by the DN of a particular node in the directory
tree. For example, ldap://ldapserver:10389/ou=system.
- `authentication` - specifies the authentication method used when binding to the LDAP server. Can take either of
the values, `simple` (username and password) or `none` (anonymous).
- `connectionUsername` - the DN of the user that opens the connection to the directory server. For example,
`uid=admin,ou=system`. Directory servers generally require clients to present username/password credentials in order
to open a connection.
- `connectionPassword` - the password that matches the DN from `connectionUsername`. In the directory server,
in the DIT, the password is normally stored as a `userPassword` attribute in the corresponding directory entry.
- `connectionProtocol` - currently, the only supported value is a blank string. In future, this option will allow
you to select the Secure Socket Layer (SSL) for the connection to the directory server. This option must be set
explicitly to an empty string, because it has no default value.
- `userBase` - selects a particular subtree of the DIT to search for user entries. The subtree is specified by a
DN, which specifes the base node of the subtree. For example, by setting this option to `ou=User,ou=ActiveMQ,ou=system`,
the search for user entries is restricted to the subtree beneath the `ou=User,ou=ActiveMQ,ou=system` node.
- `userSearchMatching` - specifies an LDAP search filter, which is applied to the subtree selected by `userBase`.
Before passing to the LDAP search operation, the string value you provide here is subjected to string substitution,
as implemented by the `java.text.MessageFormat` class. Essentially, this means that the special string, `{0}`, is
substituted by the username, as extracted from the incoming client credentials.
After substitution, the string is interpreted as an LDAP search filter, where the LDAP search filter syntax is
defined by the IETF standard, RFC 2254. A short introduction to the search filter syntax is available from Oracle's
JNDI tutorial, [Search Filters](http://download.oracle.com/javase/jndi/tutorial/basics/directory/filter.html).
For example, if this option is set to `(uid={0})` and the received username is `jdoe`, the search filter becomes
`(uid=jdoe)` after string substitution. If the resulting search filter is applied to the subtree selected by the
user base, `ou=User,ou=ActiveMQ,ou=system`, it would match the entry, `uid=jdoe,ou=User,ou=ActiveMQ,ou=system`
(and possibly more deeply nested entries, depending on the specified search depth—see the `userSearchSubtree` option).
- `userSearchSubtree` - specify the search depth for user entries, relative to the node specified by `userBase`.
This option is a boolean. `false` indicates it will try to match one of the child entries of the `userBase` node
(maps to `javax.naming.directory.SearchControls.ONELEVEL_SCOPE`). `true` indicates it will try to match any entry
belonging to the subtree of the `userBase` node (maps to `javax.naming.directory.SearchControls.SUBTREE_SCOPE`).
- `userRoleName` - specifies the name of the multi-valued attribute of the user entry that contains a list of
role names for the user (where the role names are interpreted as group names by the broker's authorization plug-in).
If you omit this option, no role names are extracted from the user entry.
- `roleBase` - if you want to store role data directly in the directory server, you can use a combination of role
options (`roleBase`, `roleSearchMatching`, `roleSearchSubtree`, and `roleName`) as an alternative to (or in addition
to) specifying the `userRoleName` option. This option selects a particular subtree of the DIT to search for role/group
entries. The subtree is specified by a DN, which specifes the base node of the subtree. For example, by setting this
option to `ou=Group,ou=ActiveMQ,ou=system`, the search for role/group entries is restricted to the subtree beneath
the `ou=Group,ou=ActiveMQ,ou=system` node.
- `roleName` - specifies the attribute type of the role entry that contains the name of the role/group (e.g. C, O,
OU, etc.). If you omit this option, the role search feature is effectively disabled.
- `roleSearchMatching` - specifies an LDAP search filter, which is applied to the subtree selected by `roleBase`.
This works in a similar manner to the `userSearchMatching` option, except that it supports two substitution strings,
as follows:
- `{0}` - substitutes the full DN of the matched user entry (that is, the result of the user search). For
example, for the user, `jdoe`, the substituted string could be `uid=jdoe,ou=User,ou=ActiveMQ,ou=system`.
- `{1}` - substitutes the received username. For example, `jdoe`.
For example, if this option is set to `(member=uid={1})` and the received username is `jdoe`, the search filter
becomes `(member=uid=jdoe)` after string substitution (assuming ApacheDS search filter syntax). If the resulting
search filter is applied to the subtree selected by the role base, `ou=Group,ou=ActiveMQ,ou=system`, it matches all
role entries that have a `member` attribute equal to `uid=jdoe` (the value of a `member` attribute is a DN).
This option must always be set, even if role searching is disabled, because it has no default value.
If you use OpenLDAP, the syntax of the search filter is `(member:=uid=jdoe)`.
- `roleSearchSubtree` - specify the search depth for role entries, relative to the node specified by `roleBase`.
This option can take boolean values, as follows:
- `false` (default) - try to match one of the child entries of the roleBase node (maps to
`javax.naming.directory.SearchControls.ONELEVEL_SCOPE`).
- `true` — try to match any entry belonging to the subtree of the roleBase node (maps to
`javax.naming.directory.SearchControls.SUBTREE_SCOPE`).
- `debug` - boolean flag; if `true`, enable debugging; this is used only for testing or debugging; normally, it
should be set to `false`, or omitted; default is `false`
Add user entries under the node specified by the `userBase` option. When creating a new user entry in the directory,
choose an object class that supports the `userPassword` attribute (for example, the `person` or `inetOrgPerson` object
classes are typically suitable). After creating the user entry, add the `userPassword` attribute, to hold the user's
password.
If you want to store role data in dedicated role entries (where each node represents a particular role), create a role
entry as follows. Create a new child of the `roleBase` node, where the `objectClass` of the child is `groupOfNames`. Set
the `cn` (or whatever attribute type is specified by `roleName`) of the new child node equal to the name of the
role/group. Define a `member` attribute for each member of the role/group, setting the `member` value to the DN of the
corresponding user (where the DN is specified either fully, `uid=jdoe,ou=User,ou=ActiveMQ,ou=system`, or partially,
`uid=jdoe`).
If you want to add roles to user entries, you would need to customize the directory schema, by adding a suitable
attribute type to the user entry's object class. The chosen attribute type must be capable of handling multiple values.
#### CertificateLoginModule
The JAAS certificate authentication login module must be used in combination with SSL and the clients must be configured
with their own certificate. In this scenario, authentication is actually performed during the SSL/TLS handshake, not
directly by the JAAS certificate authentication plug-in. The role of the plug-in is as follows:
- To further constrain the set of acceptable users, because only the user DNs explicitly listed in the relevant
properties file are eligible to be authenticated.
- To associate a list of groups with the received user identity, facilitating integration with the authorization feature.
- To require the presence of an incoming certificate (by default, the SSL/TLS layer is configured to treat the
presence of a client certificate as optional).
The JAAS certificate login module stores a collection of certificate DNs in a pair of flat files. The files associate a
username and a list of group IDs with each DN.
The certificate login module is implemented by the following class:
org.apache.activemq.artemis.spi.core.security.jaas.TextFileCertificateLoginModule
The following `CertLogin` login entry shows how to configure certificate login module in the login.config file:
CertLogin {
org.apache.activemq.artemis.spi.core.security.jaas.TextFileCertificateLoginModule
debug=true
org.apache.activemq.jaas.textfiledn.user="users.properties"
org.apache.activemq.jaas.textfiledn.role="roles.properties";
};
In the preceding example, the JAAS realm is configured to use a single `org.apache.activemq.artemis.spi.core.security.jaas.TextFileCertificateLoginModule`
login module. The options supported by this login module are as follows:
- `debug` - boolean flag; if true, enable debugging; this is used only for testing or debugging; normally,
it should be set to `false`, or omitted; default is `false`
- `org.apache.activemq.jaas.textfiledn.user` - specifies the location of the user properties file (relative to the
directory containing the login configuration file).
- `org.apache.activemq.jaas.textfiledn.role` - specifies the location of the role properties file (relative to the
directory containing the login configuration file).
- `reload` - boolean flag; whether or not to reload the properties files when a modification occurs; default is `false`
In the context of the certificate login module, the `users.properties` file consists of a list of properties of the form,
`UserName=StringifiedSubjectDN`. For example, to define the users, system, user, and guest, you could create a file like
the following:
system=CN=system,O=Progress,C=US
user=CN=humble user,O=Progress,C=US
guest=CN=anon,O=Progress,C=DE
Each username is mapped to a subject DN, encoded as a string (where the string encoding is specified by RFC 2253). For
example, the system username is mapped to the `CN=system,O=Progress,C=US` subject DN. When performing authentication,
the plug-in extracts the subject DN from the received certificate, converts it to the standard string format, and
compares it with the subject DNs in the `users.properties` file by testing for string equality. Consequently, you must
be careful to ensure that the subject DNs appearing in the `users.properties` file are an exact match for the subject
DNs extracted from the user certificates.
Note: Technically, there is some residual ambiguity in the DN string format. For example, the `domainComponent` attribute
could be represented in a string either as the string, `DC`, or as the OID, `0.9.2342.19200300.100.1.25`. Normally, you do
not need to worry about this ambiguity. But it could potentially be a problem, if you changed the underlying
implementation of the Java security layer.
The easiest way to obtain the subject DNs from the user certificates is by invoking the `keytool` utility to print the
certificate contents. To print the contents of a certificate in a keystore, perform the following steps:
1. Export the certificate from the keystore file into a temporary file. For example, to export the certificate with
alias `broker-localhost` from the `broker.ks` keystore file, enter the following command:
keytool -export -file broker.export -alias broker-localhost -keystore broker.ks -storepass password
After running this command, the exported certificate is in the file, `broker.export`.
1. Print out the contents of the exported certificate. For example, to print out the contents of `broker.export`,
enter the following command:
keytool -printcert -file broker.export
Which should produce output similar to that shown here:
Owner: CN=localhost, OU=broker, O=Unknown, L=Unknown, ST=Unknown, C=Unknown
Issuer: CN=localhost, OU=broker, O=Unknown, L=Unknown, ST=Unknown, C=Unknown
Serial number: 4537c82e
Valid from: Thu Oct 19 19:47:10 BST 2006 until: Wed Jan 17 18:47:10 GMT 2007
Certificate fingerprints:
MD5: 3F:6C:0C:89:A8:80:29:CC:F5:2D:DA:5C:D7:3F:AB:37
SHA1: F0:79:0D:04:38:5A:46:CE:86:E1:8A:20:1F:7B:AB:3A:46:E4:34:5C
The string following `Owner:` gives the subject DN. The format used to enter the subject DN depends on your
platform. The `Owner:` string above could be represented as either `CN=localhost,\ OU=broker,\ O=Unknown,\ L=Unknown,\ ST=Unknown,\ C=Unknown`
or `CN=localhost,OU=broker,O=Unknown,L=Unknown,ST=Unknown,C=Unknown`.
The `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:
admins=system
users=system,user
guests=guest
The simplest way to make the login configuration available to JAAS is to add the directory containing the file,
`login.config`, to your CLASSPATH.
## Changing the username/password for clustering
In order for cluster connections to work correctly, each node in the
cluster must make connections to the other nodes. The username/password
they use for this should always be changed from the installation default
to prevent a security risk.
Please see [Management](management.md) for instructions on how to do this.
## Securing the console
Artemis comes with a web console that allows user to browse Artemis documentation via an embedded server. By default the
web access is plain HTTP. It is configured in `bootstrap.xml`:
<web bind="http://localhost:8161" path="web">
<app url="jolokia" war="jolokia-war-1.3.3.war"/>
</web>
Alternatively you can edit the above configuration to enable secure access using HTTPS protocol. e.g.:
<web bind="https://localhost:8443"
path="web"
keyStorePath="${artemis.instance}/etc/keystore.jks"
keyStorePassword="password">
<app url="jolokia" war="jolokia-war-1.3.3.war"/>
</web>
As shown in the example, to enable https the first thing to do is config the `bind` to be an `https` url. In addition,
You will have to configure a few extra properties desribed as below.
- `keyStorePath` - The path of the key store file.
- `keyStorePassword` - The key store's password.
- `clientAuth` - The boolean flag indicates whether or not client authentication is required. Default is `false`.
- `trustStorePath` - The path of the trust store file. This is needed only if `clientAuth` is `true`.
- `trustStorePassword` - The trust store's password.
## Controlling JMS ObjectMessage deserialization
Artemis provides a simple class filtering mechanism with which a user can specify which
packages are to be trusted and which are not. Objects whose classes are from trusted packages
can be deserialized without problem, whereas those from 'not trusted' packages will be denied
deserialization.
Artemis keeps a `black list` to keep track of packages that are not trusted and a `white list`
for trusted packages. By default both lists are empty, meaning any serializable object is
allowed to be deserialized. If an object whose class matches one of the packages in black list,
it is not allowed to be deserialized. If it matches one in the white list
the object can be deserialized. If a package appears in both black list and white list,
the one in black list takes precedence. If a class neither matches with `black list`
nor with the `white list`, the class deserialization will be denied
unless the white list is empty (meaning the user doesn't specify the white list at all).
A class is considered as a 'match' if
- its full name exactly matches one of the entries in the list.
- its package matches one of the entries in the list or is a sub-package of one of the entries.
For example, if a class full name is "org.apache.pkg1.Class1", some matching entries could be:
- `org.apache.pkg1.Class1` - exact match.
- `org.apache.pkg1` - exact package match.
- `org.apache` -- sub package match.
A `*` means 'match-all' in a black or white list.
### Specifying black list and white list via Connection Factories
To specify the white and black lists one can append properties `deserializationBlackList` and `deserializationWhiteList` respectively
to a Connection Factory's url string. For example:
ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory("vm://0?deserializationBlackList=org.apache.pkg1,org.some.pkg2");
The above statement creates a factory that has a black list contains two forbidden packages, "org.apache.pkg1" and "org.some.pkg2",
separated by a comma.
You can also set the values via ActiveMQConnectionFactory's API:
public void setDeserializationBlackList(String blackList);
public void setDeserializationWhiteList(String whiteList);
Again the parameters are comma separated list of package/class names.
### Specifying black list and white list via system properties
There are two system properties available for specifying black list and white list:
- `org.apache.activemq.artemis.jms.deserialization.whitelist` - comma separated list of entries for the white list.
- `org.apache.activemq.artemis.jms.deserialization.blacklist` - comma separated list of entries for the black list.
Once defined, all JMS object message deserialization in the VM is subject to checks against the two lists. However if you create a ConnectionFactory
and set a new set of black/white lists on it, the new values will override the system properties.
### Specifying black list and white list for resource adapters
Message beans using a JMS resource adapter to receive messages can also control their object deserialization via properly configuring relevant
properties for their resource adapters. There are two properties that you can configure with connection factories in a resource adapter:
- `deserializationBlackList` - comma separated values for black list
- `deserializationWhiteList` - comma separated values for white list
These properties, once specified, are eventually set on the corresponding internal factories.
### Specifying black list and white list for REST interface
Apache Artemis REST interface ([Rest](rest.md)) allows interactions between jms client and rest clients.
It uses JMS ObjectMessage to wrap the actual user data between the 2 types of clients and deserialization
is needed during this process. If you want to control the deserialization for REST, you need to set the
black/white lists for it separately as Apache Artemis REST Interface is deployed as a web application.
You need to put the black/white lists in its web.xml, as context parameters, as follows
<web-app>
<context-param>
<param-name>org.apache.activemq.artemis.jms.deserialization.whitelist</param-name>
<param-value>some.allowed.class</param-value>
</context-param>
<context-param>
<param-name>org.apache.activemq.artemis.jms.deserialization.blacklist</param-name>
<param-value>some.forbidden.class</param-value>
</context-param>
...
</web-app>
The param-value for each list is a comma separated string value representing the list.