LibraryPrintFeedback

Security Guide

Version 7.1

December 2012
Trademark Disclaimer
Third Party Acknowledgements

Updated: 07 Aug 2014

Revision History

Table of Contents

1. SSL/TLS Security
Introduction to SSL/TLS
Secure Transport Protocols
Java Keystores
How to Use X.509 Certificates
Configuring JSSE System Properties
Setting Security Context for the Openwire/SSL Protocol
Securing Java Clients
SSL/TLS Tutorial
2. Managing Certificates
What is an X.509 Certificate?
Certification Authorities
Commercial Certification Authorities
Private Certification Authorities
Certificate Chaining
Special Requirements on HTTPS Certificates
Creating Your Own Certificates
3. Authentication
Programming Client Credentials
Configuring Credentials for Broker Components
Simple Authentication Plug-In
JAAS Authentication
Introduction to JAAS
JAAS Username/Password Authentication Plug-In
JAAS Certificate Authentication Plug-In
JAAS Dual Authentication Plug-In
JAAS Guest Login Module
JAAS LDAP Login Module
Broker-to-Broker Authentication
4. Authorization
Simple Authorization Plug-In
LDAP Authorization Plug-In
Programming Message-Level Authorization
5. LDAP Tutorial
Tutorial Overview
Tutorial: Install a Directory Server and Browser
Tutorial: Add User Entries and Group Entries
Tutorial: Enable LDAP Authentication in the Broker and its Clients
Tutorial: Add Authorization Entries
Tutorial: Enable LDAP Authorization in the Broker
A. ASN.1 and Distinguished Names
ASN.1
Distinguished Names
B. LDAP Entries as an LDIF File
Importing from LDIF
Index

List of Figures

1.1. Target-Only Authentication Scenario
1.2. Mutual Authentication Scenario
2.1. A Certificate Chain of Depth 2
2.2. A Certificate Chain of Depth 3
5.1. New LDAP Connection Wizard
5.2. Authentication Step of New LDAP Connection
5.3. New Entry Wizard
5.4. Distinguished Name Step of New Entry Wizard
5.5. DIT after Creating ActiveMQ, User, and Group Nodes
5.6. Attributes Step of New Entry Wizard
5.7. Attributes Step of New Entry Wizard
5.8. Attributes Step of New Entry Wizard
5.9. Complete Tree of User Entries and Group Entries
5.10. DIT after Creating Destination, Queue, and Topic Nodes
5.11. DIT after Creating Children of Queue and Topic Nodes
5.12. Attributes of the cn=admin Permission Node
5.13. DIT after Creating Children of Queue and Topic Nodes

List of Tables

1.1. Secure Transport Protocols
1.2. JSSE System Properties
A.1. Commonly Used Attribute Types

List of Examples

1.1. Java Client Using the ActiveMQSslConnectionFactory Class
2.1. OpenSSL Configuration
2.2. Creating a CA Certificate
2.3. Creating a CSR
2.4. Converting a Signed Certificate to PEM
2.5. Importing a Certificate Chain
2.6. Adding a CA to the Trust Store
2.7. Creating a Certificate and Private Key using Keytool
2.8. Signing a CSR
3.1. Simple Authentication Configuration
3.2. Enabling Anonymous Access
3.3. JAAS Login Configuration File Format
3.4. JAAS Login Entry for Simple Authentication
3.5. JAAS Login Entry for Certificate Authentication
3.6. Contents of an Exported Certificate
3.7. JAAS Login Entries for Secure and Insecure Connections
3.8. Guest Login Accepting No Credentials or Invalid Credentials
3.9. Guest Login Accepting No Credentials Only
3.10. LDAP Login Entry
4.1. Simple Authorization Plug-In Configuration
4.2. Setting Access Permissions for Advisory Destinations
4.3. LDAP Authorization Plug-In Configuration
4.4. Implementation of MessageAuthorizationPolicy
B.1. LDIF for the LDAP Tutorial

The Secure Sockets Layer (SSL) protocol was originally developed by Netscape Corporation to provide a mechanism for secure communication over the Internet. Subsequently, the protocol was adopted by the Internet Engineering Task Force (IETF) and renamed to Transport Layer Security (TLS). The latest specification of the TLS protocol is RFC 5246.

The SSL/TLS protocol sits between an application protocol layer and a reliable transport layer (such as TCP/IP). It is independent of the application protocol and can thus be layered underneath many different protocols, for example: HTTP, FTP, SMTP, and so on.

An X.509 certificate provides a way of binding an identity (in the form of an X.500 distinguished name) to a public key. X.509 is a standard specified by the IETF and the most recent specification is RFC 4158. The X.509 certificate consists essentially of an identity concatenated with a public key, with the whole certificate being digitally signed in order to guarantee the association between the identity and the public key.

But who signs the certificate? It has to be someone (or some identity) that you trust. The certificate signer could be one of the following:

  • Self—if the certificate signs itself, it is called a self-signed certificate. If you need to deploy a self-signed certificate, the certificate must be obtained from a secure channel. The only guarantee you have of the certificate's authenticity is that you obtained it from a trusted source.

  • CA certificate—a more scalable solution is to sign certificates using a Certificate Authority (CA) certificate. In this case, you only need to be careful about deploying the original CA certificate (that is, obtaining it through a secure channel). All of the certificates signed by this CA, on the other hand, can be distributed over insecure, public channels. The trusted CA can then be used to verify the signature on the certificates. In this case, the CA certificate is self-signed.

  • Chain of CA certificates—an extension of the idea of signing with a CA certificate is to use a chain of CA certificates. For example, certificate X could be signed by CA foo, which is signed by CA bar. The last CA certificate in the chain (the root certificate) is self-signed.

For more details about managing X.509 certificates, see Managing Certificates.

The keystore repository is protected by a store password, which is defined at the same time the keystore is created. Every time you attempt to access or modify the keystore, you must provide the store password.

[Note]Note

The store password can also be referred to as a keystore password or a truststore password, depending on what kind of entries are stored in the keystore file. The function of the password in both cases is the same: that is, to unlock the keystore file.

Various combinations of target and client authentication are supported by the SSL/TLS protocols. In general, SSL/TLS authentication scenarios are controlled by selecting a specific cipher suite (or cipher suites) and by setting the WantClientAuth or NeedClientAuth flags in the SSL/TLS protocol layer. The following list describes all of the possible authentication scenarios:

Table 1.2 shows the JSSE system properties that can be used to configure SSL/TLS security for the SSL (Openwire over SSL), HTTPS (Openwire over HTTPS), and Stomp+SSL (Stomp over SSL) transport protocols.

Table 1.2. JSSE System Properties

System Property NameDescription
javax.net.ssl.keyStoreLocation of the Java keystore file containing an application process's own certificate and private key. On Windows, the specified pathname must use forward slashes, /, in place of backslashes, \.
javax.net.ssl.keyStorePassword

Password to access the private key from the keystore file specified by javax.net.ssl.keyStore. This password is used twice:

  • To unlock the keystore file (store password), and

  • To decrypt the private key stored in the keystore (key password).

In other words, the JSSE framework requires these passwords to be identical.

javax.net.ssl.keyStoreType(Optional) For Java keystore file format, this property has the value jks (or JKS). You do not normally specify this property, because its default value is already jks.
javax.net.ssl.trustStore

Location of the Java keystore file containing the collection of CA certificates trusted by this application process (trust store). On Windows, the specified pathname must use forward slashes, /, in place of backslashes, \.

If a trust store location is not specified using this property, the SunJSSE implementation searches for and uses a keystore file in the following locations (in order):

  1. $JAVA_HOME/lib/security/jssecacerts

  2. $JAVA_HOME/lib/security/cacerts

javax.net.ssl.trustStorePasswordPassword to unlock the keystore file (store password) specified by javax.net.ssl.trustStore.
javax.net.ssl.trustStoreType(Optional) For Java keystore file format, this property has the value jks (or JKS). You do not normally specify this property, because its default value is already jks.
javax.net.debugTo switch on logging for the SSL/TLS layer, set this property to ssl.

[Warning]Warning

The default trust store locations (in the jssecacerts and the cacerts directories) present a potential security hazard. If you do not take care to manage the trust stores under the JDK installation or if you do not have control over which JDK installation is used, you might find that the effective trust store is too lax.

To be on the safe side, it is recommended that you always set the javax.net.ssl.trustStore property for a secure client or server, so that you have control over the CA certificates trusted by your application.

Apart from configuration using JSSE system properties, the Openwire/SSL protocol (with schema, ssl:) also supports an option to set its SSL security context using the broker configuration file.

[Note]Note

The methods for setting the security context described in this section are available exclusively for the Openwire/SSL protocol. These features are not supported by the HTTPS protocol.

Before you can build and run the sample clients, you must have installed the Apache Ant build tool, version 1.6 or later (see http://ant.apache.org/).

The OpenWire examples depend on the sample producer and consumer clients located in the following directory:

FuseInstallDir/fuse-message-broker-Version/example

Open a new command prompt and run the setSslOpts.[bat|sh] script to initialize the SSL_OPTS variable in the broker's environment. Now run the default broker by entering the following at a command line:

activemq

The default broker automatically takes its configuration from the default configuration file.

[Note]Note

The activemq script automatically sets the ACTIVEMQ_HOME and ACTIVEMQ_BASE environment variables to FuseInstallDir/fuse-message-broker-Version by default. If you want the activemq script to pick up its configuration from a non-default conf directory, you can set ACTIVEMQ_BASE explicitly in your environment. The configuration files will then be taken from $ACTIVEMQ_BASE/conf.

A CA consists of a set of tools for generating and managing certificates and a database that contains all of the generated certificates. When setting up a system, it is important to choose a suitable CA that is sufficiently secure for your requirements.

There are two types of CA you can use:

  • commercial CAs are companies that sign certificates for many systems.

  • private CAs are trusted nodes that you set up and use to sign certificates for your system only.

One software package that allows you to set up a private CA is OpenSSL, http://www.openssl.org. OpenSSL is derived from SSLeay, an implementation of SSL developed by Eric Young (). The OpenSSL package includes basic command line utilities for generating and signing certificates. Complete documentation for the OpenSSL command line utilities is available at http://www.openssl.org/docs.

Using the subject DN’s Common Name for the certificate identity has the disadvantage that only one host name can be specified at a time. If you deploy a certificate on a multi-homed host, however, you might find it is practical to allow the certificate to be used with any of the multi-homed host names. In this case, it is necessary to define a certificate with multiple, alternative identities, and this is only possible using the subjectAltName certificate extension.

For example, if you have a multi-homed host that supports connections to either of the following host names:

www.progress.com
fusesource.com

Then you can define a subjectAltName that explicitly lists both of these DNS host names. If you generate your certificates using the openssl utility, edit the relevant line of your openssl.cfg configuration file to specify the value of the subjectAltName extension, as follows:

subjectAltName=DNS:www.progress.com,DNS:fusesource.com

Where the HTTPS protocol matches the server host name against either of the DNS host names listed in the subjectAltName (the subjectAltName takes precedence over the Common Name).

The HTTPS protocol also supports the wildcard character, *, in host names. For example, you can define the subjectAltName as follows:

subjectAltName=DNS:*.fusesource.com

This certificate identity matches any three-component host name in the domain fusesource.com.

[Warning]Warning

You must never use the wildcard character in the domain name (and you must take care never to do this accidentally by forgetting to type the dot, ., delimiter in front of the domain name). For example, if you specified *fusesource.com, your certificate could be used on any domain that ends in the letters fusesource.

You can download the OpenSSL utilities from http://openssl.org/.

This section describes using the OpenSSL command-line utilities to create certificates. Further documentation of the OpenSSL command-line utilities can be obtained at http://www.openssl.org/docs.

To create your own CA and certificates:

  1. Add the OpenSSL bin directory to your path.

  2. Create your own private CA.

    1. Create the directory structure for the CA.

      The directory structure should be:

      • X509CA/ca

      • X509CA/certs

      • X509CA/newcerts

      • X509CA/crl

      Where X509CA is the name of the CA's home directory.

    2. Copy the openssl.cfg file from your OpenSSL installation to your X509CA directory.

    3. Open your copy of openssl.cfg in a text editor.

    4. Edit the [CA_default] section to look like Example 2.1.


      [Tip]Tip

      You might decide to edit other details of the OpenSSL configuration at this point. For more details, see the OpenSSL documentation.

    5. Initialize the CA database as described in CA database files.

    6. Create a new self-signed CA certificate and private key with the command:

      openssl req -x509 -new -config X509CA/openssl.cfg -days 365 -out X509CA/ca/new_ca.pem -keyout X509CA/ca/new_ca_pk.pem

      You are prompted for a pass phrase for the CA private key and details of the CA distinguished name as shown in Example 2.2.


      [Note]Note

      The security of the CA depends on the security of the private key file and the private key pass phrase used in this step.

      You must ensure that the file names and location of the CA certificate and private key, new_ca.pem and new_ca_pk.pem, are the same as the values specified in openssl.cfg during Step 2.d.

  3. Create signed certificates in a Java keystore.

    1. Generate a certificate and private key pair using the keytool -genkeypair command.

      For details on the options to use when using keytool -genkeypair see Generate a certificate and private key pair.

    2. Create a certificate signing request using the keystore -certreq command.

      Example 2.3 creates a new certificate signing request for the fusesample.jks certificate and exports it to the fusesample_csr.pem file.


    3. Sign the CSR using the openssl ca command.

      You will prompted to enter the CA private key pass phrase you used when creating the CA in Step 2.f).

      See Signing a CSR for details on the options to use when signing the CSR.

    4. Convert the signed certificate to PEM only format using the openssl x509 command with the -outform option set to PEM.

      Example 2.4 converts the signed certificate fusesigned.pem.


    5. Concatenate the CA certificate file and the converted, signed certificate file to form a certificate chain.

      The CA certificate file is stored in the CA's ca directory. For example, the certificate file for the CA created in Step 2.f would be ca/new_ca.pem.

    6. Import the new certificate's full certificate chain into the Java keystore using the keytool -import command.

      Example 2.5 imports the chain fusesample.chain into the fusesample.jks keystore.


  4. Repeat Step 3 to create a full set of certificates for your system.

  5. Add trusted CAs to your Java trust store.

    1. Assemble the collection of trusted CA certificates that you want to deploy.

      The trusted CA certificates can be obtained from public CAs or private CAs. The trusted CA certificates can be in any format that is compatible with the Java keystore utility; for example, PEM format. All you need are the certificates themselves—the private keys and passwords are not required.

    2. Add a CA certificate to the trust store using the keytool -import command.

      Example 2.6 adds the CA certificate cacert.pem, in PEM format, to a JKS trust store.


      truststore.ts is a keystore file containing CA certificates. If this file does not already exist, the keytool command creates one. StorePass is the password required to access the keystore file.

    3. Repeat Step 5.b to add all of the CA certificates to the trust store.

To generate a certificate and private key pair you use the keytool -genkeypair command. For example, Example 2.7 creates a certificate and key pair that are valid for 365 days and is stored in the keystore file fusesample.jks. The generated key store entry will use the alias fuse and the password fusepass.


Because the specified keystore, fusessample.jks, did not exist prior to issuing the command implicitly creates a new keystore and sets its password to fusestorepass.

The -dname and -validity flags define the contents of the newly created X.509 certificate.

The -dname flag specifies the subject DN. For more details about DN format, see Appendix A. Some parts of the subject DN must match the values in the CA certificate (specified in the CA Policy section of the openssl.cfg file). The default openssl.cfg file requires the following entries to match:

  • Country Name (C)

  • State or Province Name (ST)

  • Organization Name (O)

[Note]Note

If you do not observe the constraints, the OpenSSL CA will refuse to sign the certificate (see Step 2.f ).

The -validity flag specifies the number of days for which the certificate is valid.

The JAAS login configuration file has the general format shown in Example 3.3.


Where the file format can be explained as follows:

  • LoginEntry labels a single entry in the login configuration. An application is typically configured to search for a particular LoginEntry label (for example, in Fuse MQ Enterprise the LoginEntry label to use is specifed in the broker configuration file). Each login entry contains a list of login modules that are invoked in order.

  • ModuleClass is the fully-qualified class name of a JAAS login module. For example, org.apache.activemq.jaas.PropertiesLoginModule is the class name of Fuse MQ Enterprise's JAAS simple authentication login module.

  • Flag determines how to react when the current login module reports an authentication failure. The Flag can have one of the following values:

    • required—authentication of this login module must succeed. Always proceed to the next login module in this entry, irrespective of success or failure.

    • requisite—authentication of this login module must succeed. If success, proceed to the next login module; if failure, return immediately without processing the remaining login modules.

    • sufficient—authentication of this login module is not required to succeed. If success, return immediately without processing the remaining login modules; if failure, proceed to the next login module.

    • optional—authentication of this login module is not required to succeed. Always proceed to the next login module in this entry, irrespective of success or failure.

  • Option="Value"—after the Flag, you can pass zero or more option settings to the login module. The options are specified in the form of a space-separated list, where each option has the form Option="Value". The login module line is terminated by a semicolon, ;.

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]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:

Example 3.9 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.


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 sucessfully 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 sucessfully authenticates the user and returns immediately. The properties login module is not invoked.

The LDAP login entry supports the following options:

To configure the simple authorization plug-in, add an authorizationPlugin element to the list of plug-ins in the broker's configuration, as shown in Example 4.1.


The simple authorization plug-in is specified as a map of destination entries. The map is entered in the configuration using a authorizationMap element wrapped in a map element.

The authorization map is made up of two elements:

  • authorizationEntries—a collection of authroizationEntry elements that define the permissions assigned to authorized users have for destinations whose name matches the selector

  • tempDestinationAuthorizationEntry—defines the permissions assigned to authorized users have for temporary destinations

To configure the LDAP authorization plug-in, add the authorizationPlugin element to the list of plug-ins in the broker configuration, as shown in Example 4.3.

Example 4.3. LDAP Authorization Plug-In Configuration

<beans ...>
  <broker ...>
    ...
    <plugins>
      ...
      <authorizationPlugin>
        <map>
          <bean id="lDAPAuthorizationMap" class="org.apache.activemq.security.LDAPAuthorizationMap"
                xmlns="http://www.springframework.org/schema/beans">
            <property name="initialContextFactory" value="com.sun.jndi.ldap.LdapCtxFactory"/>
            <property name="connectionURL" value="ldap://localhost:10389"/>
            <property name="authentication" value="simple"/>
            <property name="connectionUsername" value="uid=admin,ou=system"/>
            <property name="connectionPassword" value="secret"/>
            <property name="connectionProtocol" value=""/>
            <property name="topicSearchMatchingFormat"
                      value="cn={0},ou=Topic,ou=Destination,ou=ActiveMQ,ou=system"/>
            <property name="topicSearchSubtreeBool" value="true"/>
            <property name="queueSearchMatchingFormat"
                      value="cn={0},ou=Queue,ou=Destination,ou=ActiveMQ,ou=system"/>
            <property name="queueSearchSubtreeBool" value="true"/>
            <property name="advisorySearchBase"
                      value="cn=ActiveMQ.Advisory,ou=Topic,ou=Destination,ou=ActiveMQ,ou=system"/>
            <property name="tempSearchBase"
                      value="cn=ActiveMQ.Temp,ou=Topic,ou=Destination,ou=ActiveMQ,ou=system"/>
            <property name="adminBase" value="(cn=admin)"/>
            <property name="adminAttribute" value="member"/>
            <property name="readBase" value="(cn=read)"/>
            <property name="readAttribute" value="member"/>
            <property name="writeBase" value="(cn=write)"/>
            <property name="writeAttribute" value="member"/>
          </bean>
        </map>
      </authorizationPlugin>
    </plugins>
    ...
  </broker>
</beans>

The LDAP authorization plug-in supports the following properties:

To configure the broker to install the message authorization policy from Example 4.4, add the following lines to the broker configuration file, conf/activemq.xml, inside the broker element:

<broker>
  ...
  <messageAuthorizationPolicy>
    <bean class="com.acme.MsgAuthzPolicy"
          xmlns="http://www.springframework.org/schema/beans"/>
  </messageAuthorizationPolicy>
  ...
</broker>

Apache Directory Server (ApacheDS) is an open-source implementation of an X.500 directory server. You can use this directory server as a store of security data for the LDAP authentication feature of Fuse MQ Enterprise.

To install Apache Directory Server, download ApacheDS 1.5 from http://directory.apache.org/apacheds/1.5/downloads.html and run the installer. During the installation process, you will be asked whether or not to install a default instance of the directory server. Choose the default instance.

If you install on the Windows platform, the default instance of the directory server is configured as a Windows service. Hence, you can stop and start the directory server using the standard Services administrative tool. If you install on a Linux or Mac OS platform, follow the instructions in Installing and Starting the Server for starting and stopping the directory server.

[Note]Note

This tutorial was tested with version 1.5.4 of Apache Directory Studio.

The Apache Directory Studio is an Eclipse-based suite of tools for administering an X.500 directory server. In particular, for this tutorial, you need the LDAP Browser feature, which enables you to create new entries in the Directory Information Tree (DIT).

There are two alternative ways of installing Apache Directory Studio:

Perform the following steps to add a user entry to the directory server:

  1. Ensure that the X.500 directory server is running (see Install Apache Directory Server).

  2. Start the LDAP Browser, as follows:

    • If you installed the standalone version of Apache Directory Studio, double-click the relevant icon to launch the application.

    • If you installed the LDAP Browser plug-in into an existing Eclipse IDE, start Eclipse and open the LDAP perspective. To open the LDAP perspective, select Window|Open Perspective|Other and in the Open Perspective dialog, select LDAP and click OK.

  3. Open a connection to the directory server. Right-click inside the Connections view in the lower left corner and select New Connection. The New LDAP Connection wizard opens.

  4. Specify the network parameters for the new connection. In the Connection name field, enter Apache Directory Server. In the Hostname field enter the name of the host where the Apache Directory Server is running. In the Port field, enter the IP port of the directory server (for the default instance of the Apache directory server, this is 10389). Click Next.


  5. Enter the parameters for simple authentication. In the Bind DN or user field, enter the DN of the administrator's account on the directory server (for the default instance of the Apache directory server, this is uid=admin,ou=system). In the Bind password field, enter the administrator's password (for the default instance of the Apache directory server, the administrator's password is secret). Click Finish.


  6. If the connection is successfully established, you should see an outline of the Directory Information Tree (DIT) in the LDAP Browser view. In the LDAP Browser view, drill down to the ou=system node, as shown.

    directory information tree in the LDAP browser
  7. The next few steps describe how to create some new nodes to hold the user entries and group entries.

    Right-click on the ou=system node and select New|New Entry. The New Entry wizard appears.

  8. In the Entry Creation Method pane, select the Create entry from scratch radiobutton. Click Next.

  9. In the Object Classes pane, select organisationalUnit from the list of Available object classes on the left and then click Add to populate the list of Selected object classes. Click Next.


  10. In the Distinguished Name pane, complete the RDN field, putting ou in front and ActiveMQ after the equals sign. Click Next and then click Finish.


  11. In a similar manner as described in steps 710, by right-clicking on the ou=ActiveMQ node and invoking the New Entry wizard, create the following organisationalUnit nodes as children of the ou=ActiveMQ node:

    ou=User,ou=ActiveMQ,ou=system
    ou=Group,ou=ActiveMQ,ou=system

    In the LDAP Browser window, you should now see the following tree:


  12. The next few steps describe how to create a jdoe user entry.

    Right-click on the ou=User node and select New|New Entry. The New Entry wizard appears.

  13. In the Entry Creation Method pane, select the Create entry from scratch radiobutton. Click Next.

  14. In the Object Classes pane, select inetOrgPerson from the list of Available object classes on the left and then click Add to populate the list of Selected object classes. Click Next.

  15. In the Distinguished Name pane, complete the RDN field, putting uid in front and jdoe after the equals sign. Click Next.

  16. Now fill in the mandatory attributes in the Attributes pane. Set the cn (common name) attribute to Jane Doe and the sn (surname) attribute to Doe.

  17. Add a userPassword attribute in the Attributes pane. Right-click inside the list of attributes and select New Attribute. The New Attribute wizard appears.

  18. From the Attribute type drop-down list, select userPassword. Click Finish.

  19. The Password Editor dialog appears. In the Enter New Password field, enter the password, sunflower. Click Ok.


  20. Click Finish, to close the New Entry wizard.

  21. The next few steps describe how to create an admin user entry.

    Right-click on the ou=User node and select New|New Entry. The New Entry wizard appears.

  22. In the Entry Creation Method pane, select the Create entry from scratch radiobutton. Click Next.

  23. In the Object Classes pane, select both account and simpleSecurityObject from the list of Available object classes on the left and then click Add to populate the list of Selected object classes. Click Next.

  24. In the Distinguished Name pane, complete the RDN field, putting uid in front and admin after the equals sign. Click Next.

  25. You are now prompted to provide a password, through the Password Editor dialog. In the Enter New Password field, enter the password, sunflower. Click Ok.


  26. Click Finish, to close the New Entry wizard.

  27. The next few steps describe how to create the admins group entry.

    Right-click on the ou=Group node and select New|New Entry. The New Entry wizard appears.

  28. In the Entry Creation Method pane, select the Create entry from scratch radiobutton. Click Next.

  29. In the Object Classes pane, select groupOfNames from the list of Available object classes on the left and then click Add to populate the list of Selected object classes. Click Next.

  30. In the Distinguished Name pane, complete the RDN field, putting cn in front and admins after the equals sign. Click Next.

  31. You are now prompted to provide a value for the mandatory member attribute, through the DN Editor dialog. In the text field, enter the last part of the DN for the admin user, uid=admin. Click Ok.


  32. Click Finish, to close the New Entry wizard.

  33. The next few steps describe how to create the users group entry.

    Right-click on the ou=Group node and select New|New Entry. The New Entry wizard appears.

  34. In the Entry Creation Method pane, select the Create entry from scratch radiobutton. Click Next.

  35. In the Object Classes pane, select groupOfNames from the list of Available object classes on the left and then click Add to populate the list of Selected object classes. Click Next.

  36. In the Distinguished Name pane, complete the RDN field, putting cn in front and users after the equals sign. Click Next.

  37. You are now prompted to provide a value for the mandatory member attribute, through the DN Editor dialog. In the text field, enter the last part of the DN for the jdoe user, uid=jdoe. Click Ok.

  38. Click Finish, to close the New Entry wizard.

  39. You should now be able to see the following tree in the LDAP Browser window:


Perform the following steps to enable LDAP authentication:

  1. Create the login configuration file. Using a text editor, create the file, login.config under the directory, $ACTIVEMQ_HOME/conf. Paste the following text into the login.config file:

    LDAPLogin {
      org.apache.activemq.jaas.LDAPLoginModule required
        debug=true
        initialContextFactory=com.sun.jndi.ldap.LdapCtxFactory
        connectionURL="ldap://localhost:10389"
        connectionUsername="uid=admin,ou=system"
        connectionPassword=secret
        connectionProtocol=""
        authentication=simple
        userBase="ou=User,ou=ActiveMQ,ou=system"
        userSearchMatching="(uid={0})"
        userSearchSubtree=false
        roleBase="ou=Group,ou=ActiveMQ,ou=system"
        roleName=cn
        roleSearchMatching="(member=uid={1})"
        roleSearchSubtree=false
        ;
    };

    Where these settings assume that the broker connects to a default instance of the Apache Directory Server running on the local host. The account with username, uid=admin,ou=system, and password, secret, is the default administration account created by the Apache server.

    [Note]Note

    If you are using the OpenLDAP Directory Server, the syntax required for the roleSearchMatching property is different. You must set it as roleSearchMatching="(member:=uid={1})".

  2. Add the LDAP authentication plug-in to the broker configuration. Open the broker configuration file, $ACTIVEMQ_HOME/conf/activemq.xml, with a text editor and add the jaasAuthenticationPlugin element, as follows:

    <beans>
      <broker ...>
        ...
        <plugins>
          <jaasAuthenticationPlugin configuration="LDAPLogin" />
        </plugins>
        ...
      </broker>
    </beans>

    The value of the configuration attribute, LDAPLogin, references the login entry from the login.config file.

  3. Comment out the mediation router elements in the broker configuration. Open the broker configuration file and comment out the camelContext element as follows:

    <beans>
      <broker ...>
        ...
      </broker>
    
      <!-- 
      <camelContext>
        ...
      </camelContext>
      -->
      ...
    </beans>

    The Camel route is not used in the current tutorial. If you left it enabled, you would have to supply it with appropriate username/password credentials, because it acts as a broker client.

  4. Add username/password credentials to the consumer tool. Edit the file, example/src/ConsumerTool.java, search for the line that creates a new ActiveMQConnectionFactory instance, and just before this line, set the credentials, user and password, as shown:

    // Java
    ...
    public void run() {
      ...
    	  user = "jdoe";
    	  password = "sunflower";
      ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory(user, password, url);
      ...
    }
  5. Add username/password credentials to the producer tool. Edit the file, example/src/ProducerTool.java, search for the line that creates a new ActiveMQConnectionFactory instance, and just before this line, set the credentials, user and password, just as you did for the consumer tool.

  6. Ensure that the X.500 directory server is running. If necessary, manually restart the X.500 directory server. If the server is not running, all broker connections will fail.

  7. Run the broker. Open a new command prompt and start the broker by entering the following command:

    activemq
  8. Run the consumer client. Open a new command prompt, change directory to example and enter the following Ant command:

    ant consumer -Durl=tcp://localhost:61616 -Dmax=100
  9. Run the producer client. Open a new command prompt, change directory to example and enter the following Ant command:

    ant producer -Durl=tcp://localhost:61616
  10. Perform a negative test. Edit one of the client source files (for example, ConsumerTool.java) and change the credentials (username and password) to some invalid values. Now, if you re-run the client, you will get an authentication error.

Perform the following steps to add authorization entries to the directory server:

  1. The next few steps describe how to create the ou=Destination, ou=Queue, and ou=Topic nodes.

    Right-click on the ou=ActiveMQ node and select New|New Entry. The New Entry wizard appears.

  2. In the Entry Creation Method pane, select the Create entry from scratch radiobutton. Click Next.

  3. In the Object Classes pane, select organisationalUnit from the list of Available object classes on the left and then click Add to populate the list of Selected object classes. Click Next.

  4. In the Distinguished Name pane, complete the RDN field, putting ou in front and Destination after the equals sign. Click Next and then click Finish.

  5. In a similar manner as described in steps 14, by right-clicking on the ou=Destination node and invoking the New Entry wizard, create the following organisationalUnit nodes as children of the ou=Destination node:

    ou=Queue,ou=Destination,ou=ActiveMQ,ou=system
    ou=Topic,ou=Destination,ou=ActiveMQ,ou=system

    In the LDAP Browser window, you should now see the following tree:


  6. The next few steps describe how to create the cn=TEST.FOO,ou=Queue,ou=Destination, cn=ActiveMQ.Advisory,ou=Topic,ou=Destination, and cn=ActiveMQ.Temp,ou=Topic,ou=Destination nodes.

    Right-click on the ou=Queue node and select New|New Entry. The New Entry wizard appears.

  7. In the Entry Creation Method pane, select the Create entry from scratch radiobutton. Click Next.

  8. In the Object Classes pane, select applicationProcess from the list of Available object classes on the left and then click Add to populate the list of Selected object classes. Click Next.

  9. In the Distinguished Name pane, complete the RDN field, putting cn in front and TEST.FOO after the equals sign. Click Next and then click Finish.

  10. In a similar manner as described in steps 69, by right-clicking on the ou=Topic node and invoking the New Entry wizard, create the following applicationProcess nodes as children of the ou=Topic node:

    cn=ActiveMQ.Advisory,ou=Topic,ou=Destination,ou=ActiveMQ,ou=system
    cn=ActiveMQ.Temp,ou=Topic,ou=Destination,ou=ActiveMQ,ou=system

    In the LDAP Browser window, you should now see the following tree:


  11. The next few steps describe how to create nodes that represent admin, read, and write permissions for the queues and topics.

    Right-click on the cn=TEST.FOO node and select New|New Entry. The New Entry wizard appears.

  12. In the Entry Creation Method pane, select the Create entry from scratch radiobutton. Click Next.

  13. In the Object Classes pane, select groupOfNames from the list of Available object classes on the left and then click Add to populate the list of Selected object classes. Click Next.

  14. In the Distinguished Name pane, complete the RDN field, putting cn in front and admin after the equals sign. Click Next.

  15. You are now prompted to provide a value for the mandatory member attribute, through the DN Editor dialog. In the text field, enter the last part of the DN for the admins group, cn=admins. Click Ok.

  16. Add another member attribute in the Attributes pane. Right-click inside the list of attributes and select New Attribute. The New Attribute wizard appears.

  17. In the Attribute type field, enter member (if you want to use the drop-down list, you must first uncheck the Hide existing attributes option). Click Finish.

  18. The DN Editor dialog opens. In the text field, enter the last part of the DN for the users group, cn=users. Click Ok.


  19. Click Finish, to close the New Entry wizard.

  20. In a similar manner as described in steps 1119, by right-clicking on the cn=TEST.FOO node and invoking the New Entry wizard, create the following groupOfNames nodes as children of the cn=TEST.FOO node:

    cn=read,cn=TEST.FOO,ou=Queue,ou=Destination,ou=ActiveMQ,ou=system
    cn=write,cn=TEST.FOO,ou=Queue,ou=Destination,ou=ActiveMQ,ou=system

    The new cn=read node and the new cn=write node should include both of the members, cn=admins and cn=users.

  21. Copy the cn=admin, cn=read, and cn=write permission nodes and paste them as children of the cn=ActiveMQ.Advisory node, as follows.

    Using a combination of mouse and keyboard, select the three nodes, cn=admin, cn=read, and cn=write, and type Ctrl-C to copy them. Select the cn=ActiveMQ.Advisory node and type Ctrl-V to paste the copied nodes as children.

  22. Similarly, copy the cn=admin, cn=read, and cn=write permission nodes and paste them as children of the cn=ActiveMQ.Temp node.

  23. In the LDAP Browser window, you should now see the following tree:


Perform the following steps to enable LDAP authorization:

  1. Add the LDAP authorization plug-in to the broker configuration. Open the broker configuration file, $ACTIVEMQ_HOME/conf/activemq.xml, with a text editor and add the authorizationPlugin element, as follows:

    <beans ...>
      <broker ...>
        ...
        <plugins>
          ...
          <authorizationPlugin>
            <map>
              <bean id="lDAPAuthorizationMap" class="org.apache.activemq.security.LDAPAuthorizationMap"
                    xmlns="http://www.springframework.org/schema/beans">
                <property name="initialContextFactory" value="com.sun.jndi.ldap.LdapCtxFactory"/>
                <property name="connectionURL" value="ldap://localhost:10389"/>
                <property name="authentication" value="simple"/>
                <property name="connectionUsername" value="uid=admin,ou=system"/>
                <property name="connectionPassword" value="secret"/>
                <property name="connectionProtocol" value=""/>
                <property name="topicSearchMatchingFormat"
                          value="cn={0},ou=Topic,ou=Destination,ou=ActiveMQ,ou=system"/>
                <property name="topicSearchSubtreeBool" value="true"/>
                <property name="queueSearchMatchingFormat"
                          value="cn={0},ou=Queue,ou=Destination,ou=ActiveMQ,ou=system"/>
                <property name="queueSearchSubtreeBool" value="true"/>
                <property name="advisorySearchBase"
                          value="cn=ActiveMQ.Advisory,ou=Topic,ou=Destination,ou=ActiveMQ,ou=system"/>
                <property name="tempSearchBase"
                          value="cn=ActiveMQ.Temp,ou=Topic,ou=Destination,ou=ActiveMQ,ou=system"/>
                <property name="adminBase" value="(cn=admin)"/>
                <property name="adminAttribute" value="member"/>
                <property name="readBase" value="(cn=read)"/>
                <property name="readAttribute" value="member"/>
                <property name="writeBase" value="(cn=write)"/>
                <property name="writeAttribute" value="member"/>
              </bean>
            </map>
          </authorizationPlugin>
        </plugins>
        ...
      </broker>
    </beans>
  2. If you have not already done so, add username/password credentials to the consumer tool, example/src/ConsumerTool.java, and to the producer tool, example/src/ProducerTool.java, as described in Tutorial: Enable LDAP Authentication in the Broker and its Clients.

  3. Ensure that the X.500 directory server is running. If necessary, manually restart the X.500 directory server. If the server is not running, all broker connections will fail.

  4. Run the broker. Open a new command prompt and start the broker by entering the following command:

    activemq
  5. Run the consumer client. Open a new command prompt, change directory to example and enter the following Ant command:

    ant consumer -Durl=tcp://localhost:61616 -Dmax=100
  6. Run the producer client. Open a new command prompt, change directory to example and enter the following Ant command:

    ant producer -Durl=tcp://localhost:61616

To recreate the directory tree for the LDAP tutorial, perform the following steps in Apache Directory Studio:

  1. Copy the contents of the LDIF from Example B.1 and paste into a text file, activemq.ldif, in any convenient location.

    [Important]Important

    Make sure to include a blank line at the end of the file, otherwise Apache Directory Studio will throw an error as it tries to read the last record.

  2. Ensure that the X.500 directory server is running.

  3. Start up Apache Directory Studio and open a connection to the directory server.

  4. In the LDAP Browser view, expand the DIT node. Right-click on the Root DSE node and select Import|LDIF Import.

  5. The LDIF Import dialog appears. In the LDIF File field, enter the location of the LDIF file to import or use the Browse button. Click Finish.

Example B.1 gives the complete LDIF for recreating the directory tree of the LDAP tutorial.

Example B.1. LDIF for the LDAP Tutorial

## ---------------------------------------------------------------------------
## Licensed to the Apache Software Foundation (ASF) under one or more
## contributor license agreements.  See the NOTICE file distributed with
## this work for additional information regarding copyright ownership.
## The ASF licenses this file to You under the Apache License, Version 2.0
## (the "License"); you may not use this file except in compliance with
## the License.  You may obtain a copy of the License at
##
## http://www.apache.org/licenses/LICENSE-2.0
##
## Unless required by applicable law or agreed to in writing, software
## distributed under the License is distributed on an "AS IS" BASIS,
## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
## See the License for the specific language governing permissions and
## limitations under the License.
## ---------------------------------------------------------------------------


##########################
## Define basic objects ##
##########################

# Uncomment if adding to open ldap
#dn: ou=system
#objectclass: organizationalUnit
#objectclass: top
#ou: system

dn: ou=ActiveMQ,ou=system
objectClass: organizationalUnit
objectClass: top
ou: ActiveMQ

dn: ou=Services,ou=system
ou: Services
objectClass: organizationalUnit
objectClass: top

dn: cn=mqbroker,ou=Services,ou=system
cn: mqbroker
objectClass: organizationalRole
objectClass: top
objectClass: simpleSecurityObject
userPassword: {SSHA}YvMAkkd66cDecNoejo8jnw5uUUBziyl0
description: Bind user for MQ broker


###################
## Define groups ##
###################


dn: ou=Group,ou=ActiveMQ,ou=system
objectClass: organizationalUnit
objectClass: top
ou: Group

dn: cn=admins,ou=Group,ou=ActiveMQ,ou=system
cn: admins
member: uid=admin
objectClass: groupOfNames
objectClass: top

dn: cn=users,ou=Group,ou=ActiveMQ,ou=system
cn: users
member: uid=jdoe
objectClass: groupOfNames
objectClass: top


##################
## Define users ##
##################


dn: ou=User,ou=ActiveMQ,ou=system
objectClass: organizationalUnit
objectClass: top
ou: User

dn: uid=admin,ou=User,ou=ActiveMQ,ou=system
uid: admin
userPassword: {SSHA}YvMAkkd66cDecNoejo8jnw5uUUBziyl0
objectClass: account
objectClass: simpleSecurityObject
objectClass: top


dn: uid=jdoe,ou=User,ou=ActiveMQ,ou=system
uid: jdoe
userPassword: {SSHA}YvMAkkd66cDecNoejo8jnw5uUUBziyl0
objectclass: inetOrgPerson
objectclass: organizationalPerson
objectclass: person
objectclass: top
cn: Jane Doe
sn: Doe


#########################
## Define destinations ##
#########################

dn: ou=Destination,ou=ActiveMQ,ou=system
objectClass: organizationalUnit
objectClass: top
ou: Destination

dn: ou=Topic,ou=Destination,ou=ActiveMQ,ou=system
objectClass: organizationalUnit
objectClass: top
ou: Topic

dn: ou=Queue,ou=Destination,ou=ActiveMQ,ou=system
objectClass: organizationalUnit
objectClass: top
ou: Queue

## TEST.FOO

dn: cn=TEST.FOO,ou=Queue,ou=Destination,ou=ActiveMQ,ou=system
cn: TEST.FOO
description: A queue
objectClass: applicationProcess
objectClass: top

dn: cn=admin,cn=TEST.FOO,ou=Queue,ou=Destination,ou=ActiveMQ,ou=system
cn: admin
description: Admin privilege group, members are roles
member: cn=admins
member: cn=users
objectClass: groupOfNames
objectClass: top

dn: cn=read,cn=TEST.FOO,ou=Queue,ou=Destination,ou=ActiveMQ,ou=system
cn: read
member: cn=users
member: cn=admins
objectClass: groupOfNames
objectClass: top

dn: cn=write,cn=TEST.FOO,ou=Queue,ou=Destination,ou=ActiveMQ,ou=system
cn: write
objectClass: groupOfNames
objectClass: top
member: cn=users
member: cn=admins



#######################
## Define advisories ##
#######################

dn: cn=ActiveMQ.Advisory,ou=Topic,ou=Destination,ou=ActiveMQ,ou=system
cn: ActiveMQ.Advisory
objectClass: applicationProcess
objectClass: top
description: Advisory topics

dn: cn=read,cn=ActiveMQ.Advisory,ou=Topic,ou=Destination,ou=ActiveMQ,ou=system
cn: read
member: cn=admins
member: cn=users
objectClass: groupOfNames
objectClass: top

dn: cn=write,cn=ActiveMQ.Advisory,ou=Topic,ou=Destination,ou=ActiveMQ,ou=system
cn: write
member: cn=admins
member: cn=users
objectClass: groupOfNames
objectClass: top

dn: cn=admin,cn=ActiveMQ.Advisory,ou=Topic,ou=Destination,ou=ActiveMQ,ou=system
cn: admin
member: cn=admins
member: cn=users
objectClass: groupOfNames
objectClass: top

######################
## Define temporary ##
######################

dn: cn=ActiveMQ.Temp,ou=Topic,ou=Destination,ou=ActiveMQ,ou=system
cn: ActiveMQ.Temp
objectClass: applicationProcess
objectClass: top
description: Temporary destinations

dn: cn=read,cn=ActiveMQ.Temp,ou=Topic,ou=Destination,ou=ActiveMQ,ou=system
cn: read
member: cn=admins
member: cn=users
objectClass: groupOfNames
objectClass: top

dn: cn=write,cn=ActiveMQ.Temp,ou=Topic,ou=Destination,ou=ActiveMQ,ou=system
cn: write
member: cn=admins
member: cn=users
objectClass: groupOfNames
objectClass: top

dn: cn=admin,cn=ActiveMQ.Temp,ou=Topic,ou=Destination,ou=ActiveMQ,ou=system
cn: admin
member: cn=admins
member: cn=users
objectClass: groupOfNames
objectClass: top

## Important: Leave a blank line after the last record!

B

Basic Encoding Rules (see BER)
BER, BER

C

CA, Integrity of the public key
choosing a host, Choosing a host for a private certification authority
commercial CAs, Commercial Certification Authorities
index file, CA database files
list of trusted, Trusted CAs
multiple CAs, Certificates signed by multiple CAs
private CAs, Private Certification Authorities
private key, creating, Procedure
security precautions, Security precautions
self-signed, Procedure
serial file, CA database files
setting up, Procedure
certificate signing request, Procedure
signing, Procedure
certificates
chaining, Certificate chain
peer, Chain of trust
public key, Contents of an X.509 certificate
self-signed, Self-signed certificate, Procedure
signing, Integrity of the public key, Procedure
signing request, Procedure
X.509, Role of certificates
chaining of certificates, Certificate chain
CSR, Procedure

D

DER, DER
Distinguished Encoding Rules (see DER)
distinguished names
definition, Overview
DN
definition, Overview
string representation, String representation of DN

I

index file, CA database files

O

OpenSSL, OpenSSL software package
OpenSSL command-line utilities, OpenSSL utilities

P

peer certificate, Chain of trust
private key, Procedure
public keys, Contents of an X.509 certificate

R

RDN, RDN
relative distinguished name (see RDN)
root certificate directory, Trusted CAs

S

self-signed CA, Procedure
self-signed certificate, Self-signed certificate
serial file, CA database files
signing certificates, Integrity of the public key
SSLeay, OpenSSL software package

T

tempDestinationAuthorizationEntry, Configuring the simple authorization plug-in, Temporary destinations
temporary destinations
authorization, Temporary destinations
trusted CAs, Trusted CAs

X

X.500, ASN.1 and Distinguished Names
X.509 certificate
definition, Role of certificates