ActiveMQ 5.10 and later provides a fully customizable security experience using Apache Shiro.
The ActiveMQ Shiro plugin can secure all aspects of ActiveMQ, from authenticating transport connections to authorizing behavior with topics and queues and everything in between.
The fastest/simplest way to enable the ShiroPlugin is to define it as a Spring bean in the broker plugins section and embed Shiro ini configuration:
This config assumes you have a simple/small set of static users that access your ActiveMQ broker. We'll cover enabling more advanced user repositories later.
The above example uses plaintext passwords, which is simple to set up and easy to use for testing, but not really secure. Most production deployments will likely want to use encrypted passwords. For example:
As you can see, two things are different than the simpler/default configuration:
To get the hashed password text values, you will want to Download Shiro's Command Line Hasher from Maven Central. Once downloaded, you can use it to create secure password hashes that you can safely copy-and-paste in to the [users] section:
It will then ask you to enter the password and then confirm it:
When this command executes, it will print out the securely-salted-iterated-and-hashed password. For example:
Take this value and place it as the password in the user definition line (followed by any desired roles, such as the advisory role). For example:
The ActiveMQ Shiro plugin can be configured in a number of ways. For example, with Java:
Or, if using traditional ActiveMQ xml, as a Spring bean in the broker plugins section. For example:
The remaining configuration examples on this page will be shown as bean XML, but know that the same configuration can be done in Java as standard JavaBeans-compatible getter and setter methods.
You can enable or disable the ShiroPlugin entirely without having to remove it from your configuration. This is convenient when testing, or when you want to enable or disable it based on a configuration parameter at startup.
A nice technique is to use Spring's PropertySourcesPlaceholderConfigurer and placeholder tokens (set shiro.enabled = true in one of your placeholder property files):
This allows you to enable or disable the Shiro plugin by simply setting a property in a .properties file without having to change your XML config.
The shiroPlugin requires a Shiro Environment to function. You must either configure the plugin with:
A Shiro Environment object contains everything that Shiro needs to operate, and this encapsulates the Shiro SecurityManager as well. If you want to construct and configure an Environment instance yourself:
Instead of configuring an Environment instance, you can construct a SecurityManager instead:
If specifying a SecurityManager instead of the Environment property, an Environment will be created automatically that wraps the configured SecurityManager.
If you don't want to construct a SecurityManager or Environment in code or xml, you can easily specify a shiro.ini file instead and an Environment/SecurityManager will automatically be created based on that:
This allows you to keep your Shiro config separate from your ActiveMQ broker configuration if you prefer.
If you want to use ini configuration and you would prefer to have all configuration in one place, you can embed the ini config instead:
The SubjectFilter exists before all other Shiro-related broker filters in the broker filter chain. It constructs a Shiro Subject instance reflecting the broker client and ensures the Subject instance is available for all downstream broker filters that may need to use the Subject to perform security operations.
The AuthenticationFilter exists immediately after the SubjectFilter in the broker filter chain. It ensures that the broker client Subject is authenticated if necessary before allowing the chain to continue. If authentication is required and the Subject is not authenticated, the broker filter chain will not be executed, ensuring only verified identities may perform further behavior.
The AuthorizationFilter exists immediately after the AuthenticationFilter in the broker filter chain. It ensures that the Subject associated with the filter chain is authorized (permitted) to perform the action being attempted before allowing the action to execute.
For example, it would ensure that the Subject is allowed to send a message to a particular topic before allowing the send operation to execute. If authorization is enabled and the Subject is not authorized to perform the desired action, the broker filter chain will not be executed.
The ShiroPlugin installs and executes the SubjectFilter before all other Shiro-related broker filters in the broker filter chain. The SubjectFilter constructs a Shiro Subject instance reflecting the broker client and ensures the Subject instance is available for all downstream broker filters that may need to use the Subject to perform security operations.
The SubjectFilter is mostly a 'behind the scenes' component of the SubjectFilter, but it does offer some customization for advanced use cases:
Unless you're deeply familiar with ActiveMQ's security model, you can safely skip to Authentication below.
A ConnectionSubjectFactory creates a Subject instance that represents the broker client's identity. The SubjectFilter's default instance is a DefaultConnectionSubjectFactory
Most ConnectionSubjectFactory implementations will simply use Shiro's Subject.Builder to create an anonymous Subject instance and let the downstream AuthenticationFilter authenticate the Subject based on any credentials associated with the connection. After authentication, the Subject will have an identity, and this is the expected flow for most connection clients.
However, if there is some other data associated with the connection that can be inspected to create a Subject instance beyond what the DefaultConnectionSubjectFactory, you can implement the ConnectionSubjectFactory interface and plug it in to the SubjectFilter:
The ActiveMQ ConnectionContext associated with broker client connections utilizes a SecurityContext object. When the SubjectFilter executes, it needs to create a Shiro-specific SecurityContext and associate it with the ConnectionContext so the Subject may be accessed downstream for all subsequent security operations.
The SubjectFilter delegates SecurityContext creation to a SecurityContextFactory instance. The DefaultSecurityContextFactory implementation returns SubjectSecurityContext instances based on the connection's associated Subject. It should be an extremely rare thing to change, but if you must configure a custom SecurityContextFactory, you can do as follows:
Note however that much of the plugin's functionality and downstream filters expect created SecurityContext instances to be SubjectSecurityContext instances.
The ShiroPlugin installs the AuthenticationFilter immediately after the SubjectFilter in the broker filter chain. The AuthenticationFilter ensures that the broker client Subject is authenticated if necessary before allowing the chain to continue. If authentication is required and the Subject is not authenticated, the broker filter chain will not be executed, ensuring only verified identities may perform further behavior.
WORK IN PROGRESS - STILL AUTHORING