ActiveMQ Simple Authentication for Consumers and Producers

By default, ActiveMQ does not request a Username or password for consumers and producers. That means, everyone who knows your broker URL is able to connect to your broker and read your messages and/or send messages. For personal development this isn’t a big issue, but for business applications security plays an important role.

Because of that, I have played around with the authentication of consumers and producers on ActiveMQ brokers.

First of all you should know, that ActiveMQ supports a users and groups based authentication.In our example we would like to have two groups:

  • senders: they are allowed to send messages into queues (write access)
  • receivers: they are allowed to consume the messages (read access)

Setup groups and users for Receiver and Consumer:

To setup those two groups and one user for each group you have to add these lines (starting with „plugins“)  to your activemq.xml :

ATTENTION:  in earlier versions (I tested it also with 5.5.1) you have to insert the plugins-element in the correct alphabetical order. See also: http://activemq.apache.org/xml-reference.html –> Alphabetically ordered xml elements (5.4 – 5.5.1)

    <!--
        The <broker> element is used to configure the ActiveMQ broker.
    -->
    <broker xmlns="http://activemq.apache.org/schema/core" brokerName="localhost" dataDirectory="${activemq.data}">

      <plugins>
        <simpleAuthenticationPlugin>
            <users>
                <authenticationUser username="superman" password="boss" groups="senders,receivers,admins" />
                <authenticationUser username="mySendingApp" password="manager" groups="senders" />
                <authenticationUser username="myReceivingApp" password="manager" groups="receivers" />
            </users>
        </simpleAuthenticationPlugin>
      </plugins>

Link groups and users to queues and topics

After that you need to grant rights to the created groups „senders“ , „receivers“ and „admins“. Add the following lines after the closing </simpleAuthenticationPlugin> tag:

<authorizationPlugin>
   <map>
       <authorizationMap>
           <authorizationEntries>
               <authorizationEntry queue=">" write="senders" read="receivers" admin="admins" />
	       <authorizationEntry topic="ActiveMQ.Advisory.>" write="senders" read="receivers" admin="admins,senders,receivers" />
           </authorizationEntries>
       </authorizationMap>
   </map>
</authorizationPlugin>

Explanation: You can specify different access rights for the single queues. In my example I allow all users from group „senders“ to write inside all queues. queue=“>“ stands for all queues. ActiveMQ uses the „>“ as Wildcard (see also the website-link below). Also I allow all receivers to read from the queue.

Maybe you are wondering about the second <authorizationEntry> . ActiveMQ-Clients creating Advisory-Topics for several reasons. For each queue a client connects to, the client tries to create a Advisory-Topic. That is the reason why I added the second line. This line defines that all clients (with correct password and username) are able to create Topics that are named „ActiveMQ.Advisory.*“.  More about ActiveMQs advisory stuff see website link below.

Now you can restart the ActiveMQ broker in order to read the new configuration.

Client side: connect to a username/password protected queue

Now we have to setup the client side to connect to a secured broker. The ConnectionFactory class provides a method called „createConnection“. There is an overloaded method of this: createConnection(String arg1 , String arg2) where arg1 is the username and arg2 is the password.

Here a short example for a listener connecting to a secured broker:

public void startListener() throws NamingException, JMSException, InterruptedException {

	// Create a JNDI API InitialContext object
	Properties props = new Properties();
	props.setProperty(Context.INITIAL_CONTEXT_FACTORY, "org.apache.activemq.jndi.ActiveMQInitialContextFactory");
	props.setProperty(Context.PROVIDER_URL, "tcp://" + server + ":61616");

	jndiContext = new InitialContext(props);
	connectionFactory = (ConnectionFactory) jndiContext.lookup("ConnectionFactory");
	destination = (Destination) jndiContext.lookup("dynamicQueues/" + queueName);

	// Connect to ActiveMQ
	connection = connectionFactory.createConnection(username, password);
	connection.setClientID(clientID);
	// this helps to ensure, that not 2 instances can connect to the broker simultaneously
	// because it is not allowed to connect to the same broker with the same clientID
	connection.start();
	session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);

	MessageConsumer subscriber = session.createConsumer(destination);
	subscriber.setMessageListener(new MessageListener() {

		@Override
		public void onMessage(Message msg) {
			try {
				System.out.println("Message arrived by consumer-ID : " + clientID + " CONTENT = " + ((TextMessage) msg).getText());
			} catch (JMSException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	});

	for (int i = 0; i &lt; 100; i++) {
		System.out.println("still alive .... " + i);
		Thread.sleep(10 * 1000);
	}
}

 

Have fun with simple secured JMS 😉

——————————————————————

Sources / Websites:

ActiveMQ Wildcards: http://activemq.apache.org/wildcards.html

ActiveMQ Sample Borker Config for secured JMS Connections: http://activemq.apache.org/complex-single-broker-configuration-stomp-only.html

ActiveMQ Advisory Topics: http://activemq.apache.org/advisory-message.html

Java API for ConnectionFactory:  http://docs.oracle.com/javaee/1.4/api/javax/jms/ConnectionFactory.html

 

Reset forgotten Linux passwords

If you forgot your Linux password, you can change it – without any rights. This article shows how:

Therefore boot in the single-user-mode. To do so, just choose the „recovery boot“ kernel while booting.

There, you can choose to drop to a root prompt.

In this terminal, just type:

passwd <username>

or, to set the root password:

passwd

After changing the password, just type reboot, to start the reboot of the system.

You now can login with your new given password.

However, not all Linux distributions allow to modify your password that way.

Change password – expiration in linux

If you just want to change a password you can use the passwd command.

If you want to set a time-limit after which the user has to change his passwort you can do that with this command:

sudo chage <username>

or:

sudo passwd -x 90 <username> ( 90 stands for 90 days )

If you want to see the password-settings for a user you can use this command:

sudo chage -l <username>

Example of the /etc/shadow file:

bc:$6$vvBxq0rK$nFUZQ3p0efbpwWUB2cZ3sk/4DX.:14673:0:99999:7:::

There are several values, which are seperated by a „:“. The first value, „bc“, is the username. The second is a hash value of the password and some other userdata.(Note: If two users have the same password, the hashes aren’t equal!

The third is the expiration date of the passwort. It gets computed by:

January 1st, 1970 + this value in days = expiration day

The fourth value is the number of days between two password changes. „0“ stands for:“not specified“

The fifth value is the number of days, the password is valid.

The sixt value is the number of days, the user should be warned before the password expires.

The seventh value is the number of days between the expiration of the password and the lock of the user account.

The last value is the expiration of the user account in days since the 1st of January in 1970.

You can edit the information as root, the tools mentioned above are only a frontend.

More information is available at: https://help.ubuntu.com/8.04/serverguide/C/user-management.html