ARTEMIS-308 security+LDAP example
This commit is contained in:
parent
9cae390645
commit
dd4a8d6879
|
@ -82,6 +82,7 @@ under the License.
|
|||
<module>request-reply</module>
|
||||
<module>scheduled-message</module>
|
||||
<module>security</module>
|
||||
<module>security-ldap</module>
|
||||
<module>send-acknowledgements</module>
|
||||
<module>spring-integration</module>
|
||||
<module>ssl-enabled</module>
|
||||
|
@ -142,7 +143,7 @@ under the License.
|
|||
<module>rest</module>
|
||||
<module>scheduled-message</module>
|
||||
<module>security</module>
|
||||
<module>security-jaas</module>
|
||||
<module>security-ldap</module>
|
||||
<module>send-acknowledgements</module>
|
||||
<module>spring-integration</module>
|
||||
|
||||
|
|
|
@ -0,0 +1,151 @@
|
|||
<?xml version='1.0'?>
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>org.apache.activemq.examples.broker</groupId>
|
||||
<artifactId>jms-examples</artifactId>
|
||||
<version>1.1.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>security-ldap</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<name>ActiveMQ Artemis JMS Security LDAP Example</name>
|
||||
|
||||
<properties>
|
||||
<activemq.basedir>${project.basedir}/../../../..</activemq.basedir>
|
||||
<version.org.apache.ds>2.0.0-M20</version.org.apache.ds>
|
||||
</properties>
|
||||
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.apache.directory.server</groupId>
|
||||
<artifactId>apacheds-parent</artifactId>
|
||||
<version>${version.org.apache.ds}</version>
|
||||
<scope>import</scope>
|
||||
<type>pom</type>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.apache.activemq</groupId>
|
||||
<artifactId>artemis-jms-client</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-simple</artifactId>
|
||||
<version>1.7.7</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.directory.server</groupId>
|
||||
<artifactId>apacheds-core-annotations</artifactId>
|
||||
<scope>compile</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-log4j12</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.directory.api</groupId>
|
||||
<artifactId>api-ldap-codec-standalone</artifactId>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.directory.server</groupId>
|
||||
<artifactId>apacheds-protocol-ldap</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.activemq</groupId>
|
||||
<artifactId>artemis-maven-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>create</id>
|
||||
<goals>
|
||||
<goal>create</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<ignore>${noServer}</ignore>
|
||||
</configuration>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>start</id>
|
||||
<goals>
|
||||
<goal>cli</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<ignore>${noServer}</ignore>
|
||||
<spawn>true</spawn>
|
||||
<testURI>tcp://localhost:61616</testURI>
|
||||
<testUser>myClusterUser</testUser>
|
||||
<testPassword>myClusterPassword</testPassword>
|
||||
<args>
|
||||
<param>run</param>
|
||||
</args>
|
||||
</configuration>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>runClient</id>
|
||||
<goals>
|
||||
<goal>runClient</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<clientClass>org.apache.activemq.artemis.jms.example.SecurityExample</clientClass>
|
||||
<args>
|
||||
<arg>${project.build.outputDirectory}/example.ldif</arg>
|
||||
</args>
|
||||
</configuration>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>stop</id>
|
||||
<goals>
|
||||
<goal>cli</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<ignore>${noServer}</ignore>
|
||||
<args>
|
||||
<param>stop</param>
|
||||
</args>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.apache.activemq.examples.broker</groupId>
|
||||
<artifactId>security-ldap</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
|
@ -0,0 +1,326 @@
|
|||
<!--
|
||||
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.
|
||||
-->
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<title>ActiveMQ Artemis JMS Security Example</title>
|
||||
<link rel="stylesheet" type="text/css" href="../../../common/common.css" />
|
||||
<link rel="stylesheet" type="text/css" href="../../../common/prettify.css" />
|
||||
<script type="text/javascript" src="../../../common/prettify.js"></script>
|
||||
</head>
|
||||
<body onload="prettyPrint()">
|
||||
<h1>JMS Security Example</h1>
|
||||
|
||||
<pre>To run the example, simply type <b>mvn verify</b> from this directory, <br>or <b>mvn -PnoServer verify</b> if you want to start and create the server manually.</pre>
|
||||
|
||||
|
||||
<p>This example shows how to configure and use security using ActiveMQ Artemis with LDAP.</p>
|
||||
|
||||
<p>With security properly configured, ActiveMQ Artemis can restrict client access to its resources, including
|
||||
connection creation, message sending/receiving, etc. This is done by configuring users and roles as well as permissions in
|
||||
the configuration files. </p>
|
||||
|
||||
<p>ActiveMQ Artemis supports wild-card security configuration. This feature makes security configuration very
|
||||
flexible and enables fine-grained control over permissions in an efficient way.</p>
|
||||
|
||||
<p>For a full description of how to configure security with ActiveMQ Artemis, please consult the user
|
||||
manual.</p>
|
||||
|
||||
<p>This example demonstrates how to configure users/roles, how to configure topics with proper permissions using wild-card
|
||||
expressions, and how they take effects in a simple program. </p>
|
||||
|
||||
<p>First we need to configure users with roles. Users and Roles are configured in <code>activemq-users.xml</code>. This example has four users
|
||||
configured as below </p>
|
||||
|
||||
<pre class="prettyprint">
|
||||
<code>
|
||||
<user name="bill" password="activemq">
|
||||
<role name="user"/>
|
||||
</user>
|
||||
|
||||
<user name="andrew" password="activemq1">
|
||||
<role name="europe-user"/>
|
||||
<role name="user"/>
|
||||
</user>
|
||||
|
||||
<user name="frank" password="activemq2">
|
||||
<role name="us-user"/>
|
||||
<role name="news-user"/>
|
||||
<role name="user"/>
|
||||
</user>
|
||||
|
||||
<user name="sam" password="activemq3">
|
||||
<role name="news-user"/>
|
||||
<role name="user"/>
|
||||
</user>
|
||||
</code>
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
Each user has three properties available: user name, password, and roles it belongs to. It should be noted that
|
||||
a user can belong to more than one role. In the above configuration, all users belong to role 'user'. User 'andrew' also
|
||||
belongs to role 'europe-user', user 'frank' also belongs to 'us-user' and 'news-user' and user 'sam' also belongs to 'news-user'.
|
||||
</p>
|
||||
<p>
|
||||
User name and password consists of a valid account that can be used to establish connections to a ActiveMQ Artemis server, while
|
||||
roles are used in controlling the access privileges against ActiveMQ Artemis topics and queues. You can achieve this control by
|
||||
configuring proper permissions in <code>broker.xml</code>, like the following
|
||||
</p>
|
||||
<pre class="prettyprint"><code>
|
||||
<security-settings>
|
||||
<!-- any user can have full control of generic topics -->
|
||||
<security-setting match="jms.topic.#">
|
||||
<permission type="createDurableQueue" roles="user"/>
|
||||
<permission type="deleteDurableQueue" roles="user"/>
|
||||
<permission type="createNonDurableQueue" roles="user"/>
|
||||
<permission type="deleteNonDurableQueue" roles="user"/>
|
||||
<permission type="send" roles="user"/>
|
||||
<permission type="consume" roles="user"/>
|
||||
</security-setting>
|
||||
|
||||
<security-setting match="jms.topic.news.europe.#">
|
||||
<permission type="createDurableQueue" roles="user"/>
|
||||
<permission type="deleteDurableQueue" roles="user"/>
|
||||
<permission type="createNonDurableQueue" roles="user"/>
|
||||
<permission type="deleteNonDurableQueue" roles="user"/>
|
||||
<permission type="send" roles="europe-user"/>
|
||||
<permission type="consume" roles="news-user"/>
|
||||
</security-setting>
|
||||
|
||||
<security-setting match="jms.topic.news.us.#">
|
||||
<permission type="createDurableQueue" roles="user"/>
|
||||
<permission type="deleteDurableQueue" roles="user"/>
|
||||
<permission type="createNonDurableQueue" roles="user"/>
|
||||
<permission type="deleteNonDurableQueue" roles="user"/>
|
||||
<permission type="send" roles="us-user"/>
|
||||
<permission type="consume" roles="news-user"/>
|
||||
</security-setting>
|
||||
</security-settings>
|
||||
</code></pre>
|
||||
|
||||
<p>Permissions can be defined on any group of queues, by using a wildcard. You can easily specify
|
||||
wildcards to apply certain permissions to a set of matching queues and topics. In the above configuration
|
||||
we have created four sets of permissions, each set matches against a special group of targets, indicated by wild-card match attributes.</p>
|
||||
|
||||
<p>You can provide a very broad permission control as a default and then add more strict control
|
||||
over specific addresses. By the above we define the following access rules:</p>
|
||||
|
||||
<li>Only role 'us-user' can create/delete and pulish messages to topics whose names match wild-card pattern 'news.us.#'.</li>
|
||||
<li>Only role 'europe-user' can create/delete and publish messages to topics whose names match wild-card pattern 'news.europe.#'.</li>
|
||||
<li>Only role 'news-user' can subscribe messages to topics whose names match wild-card pattern 'news.us.#' and 'news.europe.#'.</li>
|
||||
<li>For any other topics that don't match any of the above wild-card patterns, permissions are granted to users of role 'user'.</li>
|
||||
|
||||
<p>To illustrate the effect of permissions, three topics are deployed. Topic 'genericTopic' matches 'jms.topic.#' wild-card, topic 'news.europe.europeTopic' matches
|
||||
jms.topic.news.europe.#' wild-cards, and topic 'news.us.usTopic' matches 'jms.topic.news.us.#'.</p>
|
||||
|
||||
<p>With ActiveMQ Artemis, the security manager is also configurable. You can use JAASSecurityManager or JBossASSecurityManager based on you need. Please
|
||||
check out the activemq-beans.xml for how to do. In this example we just use the basic ActiveMQSecurityManagerImpl which reads users/roles/passwords from the xml
|
||||
file <code>activemq-users.xml</code>.
|
||||
|
||||
|
||||
<h2>Example step-by-step</h2>
|
||||
<p><i>To run the example, simply type <code>mvn verify -Pexample</code> from this directory</i></p>
|
||||
|
||||
<ol>
|
||||
<li>First we need to get an initial context so we can look-up the JMS connection factory and destination objects from JNDI. This initial context will get it's properties from the <code>client-jndi.properties</code> file in the directory <code>../common/config</code></li>
|
||||
<pre class="prettyprint">
|
||||
<code>
|
||||
InitialContext initialContext = getContext(0);
|
||||
</code>
|
||||
</pre>
|
||||
|
||||
<li>We perform lookup on the topics</li>
|
||||
<pre class="prettyprint">
|
||||
<code>
|
||||
Topic genericTopic = (Topic) initialContext.lookup("/topic/genericTopic");
|
||||
Topic europeTopic = (Topic) initialContext.lookup("/topic/europeTopic");
|
||||
Topic usTopic = (Topic) initialContext.lookup("/topic/usTopic");
|
||||
</code>
|
||||
</pre>
|
||||
|
||||
<li>We perform a lookup on the Connection Factory</li>
|
||||
<pre class="prettyprint">
|
||||
<code>
|
||||
ConnectionFactory cf = (ConnectionFactory) initialContext.lookup("/ConnectionFactory");
|
||||
</code>
|
||||
</pre>
|
||||
|
||||
<li>We try to create a JMS Connection without user/password. It will fail.</li>
|
||||
<pre class="prettyprint">
|
||||
<code>
|
||||
try
|
||||
{
|
||||
cf.createConnection();
|
||||
result = false;
|
||||
}
|
||||
catch (JMSSecurityException e)
|
||||
{
|
||||
System.out.println("Default user cannot get a connection. Details: " + e.getMessage());
|
||||
}
|
||||
</code>
|
||||
</pre>
|
||||
|
||||
<li>Bill tries to make a connection using wrong password</li>
|
||||
<pre class="prettyprint">
|
||||
<code>
|
||||
billConnection = null;
|
||||
try
|
||||
{
|
||||
billConnection = createConnection("bill", "activemq1", cf);
|
||||
result = false;
|
||||
}
|
||||
catch (JMSException e)
|
||||
{
|
||||
System.out.println("User bill failed to connect. Details: " + e.getMessage());
|
||||
}
|
||||
</code>
|
||||
</pre>
|
||||
|
||||
<li>Bill makes a good connection.</li>
|
||||
<pre class="prettyprint">
|
||||
<code>
|
||||
billConnection = createConnection("bill", "activemq", cf);
|
||||
billConnection.start();
|
||||
</code>
|
||||
</pre>
|
||||
|
||||
<li>Andrew makes a good connection</li>
|
||||
<pre class="prettyprint">
|
||||
<code>
|
||||
andrewConnection = createConnection("andrew", "activemq1", cf);
|
||||
andrewConnection.start();
|
||||
</code>
|
||||
</pre>
|
||||
|
||||
<li>Frank makes a good connection</li>
|
||||
<pre class="prettyprint">
|
||||
<code>
|
||||
frankConnection = createConnection("frank", "activemq2", cf);
|
||||
frankConnection.start();
|
||||
</code>
|
||||
</pre>
|
||||
|
||||
<li>Sam makes a good connection</li>
|
||||
<pre class="prettyprint">
|
||||
<code>
|
||||
samConnection = createConnection("sam", "activemq3", cf);
|
||||
samConnection.start();
|
||||
</code>
|
||||
</pre>
|
||||
|
||||
<li>We check every user can publish/subscribe genericTopics</li>
|
||||
<pre class="prettyprint">
|
||||
<code>
|
||||
checkUserSendAndReceive(genericTopic, billConnection, "bill");
|
||||
checkUserSendAndReceive(genericTopic, andrewConnection, "andrew");
|
||||
checkUserSendAndReceive(genericTopic, frankConnection, "frank");
|
||||
checkUserSendAndReceive(genericTopic, samConnection, "sam");
|
||||
</code>
|
||||
</pre>
|
||||
|
||||
<li>We check permissions on news.europe.europeTopic for bill: can't send and can't receive</li>
|
||||
<pre class="prettyprint">
|
||||
<code>
|
||||
checkUserNoSendNoReceive(europeTopic, billConnection, "bill", andrewConnection, frankConnection);
|
||||
</code>
|
||||
</pre>
|
||||
|
||||
<li>We check permissions on news.europe.europeTopic for andrew: can send but can't receive</li>
|
||||
<pre class="prettyprint">
|
||||
<code>
|
||||
checkUserSendNoReceive(europeTopic, andrewConnection, "andrew", frankConnection);
|
||||
</code>
|
||||
</pre>
|
||||
|
||||
<li>We check permissions on news.europe.europeTopic for frank: can't send but can receive</li>
|
||||
<pre class="prettyprint">
|
||||
<code>
|
||||
checkUserReceiveNoSend(europeTopic, frankConnection, "frank", andrewConnection);
|
||||
</code>
|
||||
</pre>
|
||||
|
||||
<li>We check permissions on news.europe.europeTopic for sam: can't send but can receive</li>
|
||||
<pre class="prettyprint">
|
||||
<code>
|
||||
checkUserReceiveNoSend(europeTopic, samConnection, "sam", andrewConnection);
|
||||
</code>
|
||||
</pre>
|
||||
|
||||
<li>We check permissions on news.us.usTopic for bill: can't send and can't receive</li>
|
||||
<pre class="prettyprint">
|
||||
<code>
|
||||
checkUserNoSendNoReceive(usTopic, billConnection, "bill");
|
||||
</code>
|
||||
</pre>
|
||||
|
||||
<li>We check permissions on news.us.usTopic for andrew: can't send and can't receive</li>
|
||||
<pre class="prettyprint">
|
||||
<code>
|
||||
checkUserNoSendNoReceive(usTopic, andrewConnection, "andrew");
|
||||
</code>
|
||||
</pre>
|
||||
|
||||
<li>We check permissions on news.us.usTopic for frank: can both send and receive</li>
|
||||
<pre class="prettyprint">
|
||||
<code>
|
||||
checkUserSendAndReceive(usTopic, frankConnection, "frank");
|
||||
</code>
|
||||
</pre>
|
||||
|
||||
<li>We check permissions on news.us.usTopic for sam: can't send but can receive</li>
|
||||
<pre class="prettyprint">
|
||||
<code>
|
||||
checkUserReceiveNoSend(usTopic, samConnection, "sam", frankConnection);
|
||||
</code>
|
||||
</pre>
|
||||
|
||||
<li>And finally, <b>always</b> remember to close your JMS connections and resources after use, in a <code>finally</code> block. Closing a JMS connection will automatically close all of its sessions, consumers, producer and browser objects</li>
|
||||
|
||||
<pre class="prettyprint">
|
||||
<code>
|
||||
finally
|
||||
{
|
||||
if (billConnection != null)
|
||||
{
|
||||
billConnection.close();
|
||||
}
|
||||
if (andrewConnection != null)
|
||||
{
|
||||
andrewConnection.close();
|
||||
}
|
||||
if (frankConnection != null)
|
||||
{
|
||||
frankConnection.close();
|
||||
}
|
||||
if (samConnection != null)
|
||||
{
|
||||
samConnection.close();
|
||||
}
|
||||
|
||||
// Also the initialContext
|
||||
if (initialContext != null)
|
||||
{
|
||||
initialContext.close();
|
||||
}
|
||||
}
|
||||
</code>
|
||||
</pre>
|
||||
</ol>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,288 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
package org.apache.activemq.artemis.jms.example;
|
||||
|
||||
import javax.jms.Connection;
|
||||
import javax.jms.ConnectionFactory;
|
||||
import javax.jms.JMSException;
|
||||
import javax.jms.JMSSecurityException;
|
||||
import javax.jms.MessageConsumer;
|
||||
import javax.jms.MessageProducer;
|
||||
import javax.jms.Session;
|
||||
import javax.jms.TextMessage;
|
||||
import javax.jms.Topic;
|
||||
import javax.naming.InitialContext;
|
||||
|
||||
import org.apache.activemq.artemis.jms.example.ldap.LdapServer;
|
||||
|
||||
public class SecurityExample {
|
||||
|
||||
public static void main(final String[] args) throws Exception {
|
||||
LdapServer ldapServer = new LdapServer(args[0]);
|
||||
|
||||
boolean result = true;
|
||||
Connection failConnection = null;
|
||||
Connection billConnection = null;
|
||||
Connection andrewConnection = null;
|
||||
Connection frankConnection = null;
|
||||
Connection samConnection = null;
|
||||
|
||||
InitialContext initialContext = null;
|
||||
try {
|
||||
// /Step 1. Create an initial context to perform the JNDI lookup.
|
||||
initialContext = new InitialContext();
|
||||
|
||||
// Step 2. perform lookup on the topics
|
||||
Topic genericTopic = (Topic) initialContext.lookup("topic/genericTopic");
|
||||
Topic europeTopic = (Topic) initialContext.lookup("topic/europeTopic");
|
||||
Topic usTopic = (Topic) initialContext.lookup("topic/usTopic");
|
||||
|
||||
// Step 3. perform a lookup on the Connection Factory
|
||||
ConnectionFactory cf = (ConnectionFactory) initialContext.lookup("ConnectionFactory");
|
||||
|
||||
// Step 4. Try to create a JMS Connection without user/password. It will fail.
|
||||
try {
|
||||
failConnection = cf.createConnection();
|
||||
result = false;
|
||||
}
|
||||
catch (JMSSecurityException e) {
|
||||
System.out.println("Default user cannot get a connection. Details: " + e.getMessage());
|
||||
}
|
||||
|
||||
// Step 5. bill tries to make a connection using wrong password
|
||||
billConnection = null;
|
||||
try {
|
||||
billConnection = createConnection("bill", "activemq1", cf);
|
||||
result = false;
|
||||
}
|
||||
catch (JMSException e) {
|
||||
System.out.println("User bill failed to connect. Details: " + e.getMessage());
|
||||
}
|
||||
|
||||
// Step 6. bill makes a good connection.
|
||||
billConnection = createConnection("bill", "activemq", cf);
|
||||
billConnection.start();
|
||||
|
||||
// Step 7. andrew makes a good connection.
|
||||
andrewConnection = createConnection("andrew", "activemq1", cf);
|
||||
andrewConnection.start();
|
||||
|
||||
// Step 8. frank makes a good connection.
|
||||
frankConnection = createConnection("frank", "activemq2", cf);
|
||||
frankConnection.start();
|
||||
|
||||
// Step 9. sam makes a good connection.
|
||||
samConnection = createConnection("sam", "activemq3", cf);
|
||||
samConnection.start();
|
||||
|
||||
// Step 10. Check every user can publish/subscribe genericTopics.
|
||||
System.out.println("------------------------Checking permissions on " + genericTopic + "----------------");
|
||||
checkUserSendAndReceive(genericTopic, billConnection, "bill");
|
||||
checkUserSendAndReceive(genericTopic, andrewConnection, "andrew");
|
||||
checkUserSendAndReceive(genericTopic, frankConnection, "frank");
|
||||
checkUserSendAndReceive(genericTopic, samConnection, "sam");
|
||||
System.out.println("-------------------------------------------------------------------------------------");
|
||||
|
||||
System.out.println("------------------------Checking permissions on " + europeTopic + "----------------");
|
||||
|
||||
// Step 11. Check permissions on news.europe.europeTopic for bill: can't send and can't receive
|
||||
checkUserNoSendNoReceive(europeTopic, billConnection, "bill");
|
||||
|
||||
// Step 12. Check permissions on news.europe.europeTopic for andrew: can send but can't receive
|
||||
checkUserSendNoReceive(europeTopic, andrewConnection, "andrew", frankConnection);
|
||||
|
||||
// Step 13. Check permissions on news.europe.europeTopic for frank: can't send but can receive
|
||||
checkUserReceiveNoSend(europeTopic, frankConnection, "frank", andrewConnection);
|
||||
|
||||
// Step 14. Check permissions on news.europe.europeTopic for sam: can't send but can receive
|
||||
checkUserReceiveNoSend(europeTopic, samConnection, "sam", andrewConnection);
|
||||
System.out.println("-------------------------------------------------------------------------------------");
|
||||
|
||||
System.out.println("------------------------Checking permissions on " + usTopic + "----------------");
|
||||
|
||||
// Step 15. Check permissions on news.us.usTopic for bill: can't send and can't receive
|
||||
checkUserNoSendNoReceive(usTopic, billConnection, "bill");
|
||||
|
||||
// Step 16. Check permissions on news.us.usTopic for andrew: can't send and can't receive
|
||||
checkUserNoSendNoReceive(usTopic, andrewConnection, "andrew");
|
||||
|
||||
// Step 17. Check permissions on news.us.usTopic for frank: can both send and receive
|
||||
checkUserSendAndReceive(usTopic, frankConnection, "frank");
|
||||
|
||||
// Step 18. Check permissions on news.us.usTopic for sam: can't send but can receive
|
||||
checkUserReceiveNoSend(usTopic, samConnection, "sam", frankConnection);
|
||||
System.out.println("-------------------------------------------------------------------------------------");
|
||||
}
|
||||
finally {
|
||||
// Step 19. Be sure to close our JMS resources!
|
||||
if (failConnection != null) {
|
||||
failConnection.close();
|
||||
}
|
||||
if (billConnection != null) {
|
||||
billConnection.close();
|
||||
}
|
||||
if (andrewConnection != null) {
|
||||
andrewConnection.close();
|
||||
}
|
||||
if (frankConnection != null) {
|
||||
frankConnection.close();
|
||||
}
|
||||
if (samConnection != null) {
|
||||
samConnection.close();
|
||||
}
|
||||
|
||||
// Also the initialContext
|
||||
if (initialContext != null) {
|
||||
initialContext.close();
|
||||
}
|
||||
|
||||
ldapServer.stop();
|
||||
}
|
||||
}
|
||||
|
||||
// Check the user can receive message but cannot send message.
|
||||
private static void checkUserReceiveNoSend(final Topic topic,
|
||||
final Connection connection,
|
||||
final String user,
|
||||
final Connection sendingConn) throws JMSException {
|
||||
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
MessageProducer producer = session.createProducer(topic);
|
||||
MessageConsumer consumer = session.createConsumer(topic);
|
||||
TextMessage msg = session.createTextMessage("hello-world-1");
|
||||
|
||||
try {
|
||||
producer.send(msg);
|
||||
throw new IllegalStateException("Security setting is broken! User " + user +
|
||||
" can send message [" +
|
||||
msg.getText() +
|
||||
"] to topic " +
|
||||
topic);
|
||||
}
|
||||
catch (JMSException e) {
|
||||
System.out.println("User " + user + " cannot send message [" + msg.getText() + "] to topic: " + topic);
|
||||
}
|
||||
|
||||
// Now send a good message
|
||||
Session session1 = sendingConn.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
producer = session1.createProducer(topic);
|
||||
producer.send(msg);
|
||||
|
||||
TextMessage receivedMsg = (TextMessage) consumer.receive(2000);
|
||||
|
||||
if (receivedMsg != null) {
|
||||
System.out.println("User " + user + " can receive message [" + receivedMsg.getText() + "] from topic " + topic);
|
||||
}
|
||||
else {
|
||||
throw new IllegalStateException("Security setting is broken! User " + user + " cannot receive message from topic " + topic);
|
||||
}
|
||||
|
||||
session1.close();
|
||||
session.close();
|
||||
}
|
||||
|
||||
// Check the user can send message but cannot receive message
|
||||
private static void checkUserSendNoReceive(final Topic topic,
|
||||
final Connection connection,
|
||||
final String user,
|
||||
final Connection receivingConn) throws JMSException {
|
||||
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
MessageProducer producer = session.createProducer(topic);
|
||||
try {
|
||||
session.createConsumer(topic);
|
||||
}
|
||||
catch (JMSException e) {
|
||||
System.out.println("User " + user + " cannot receive any message from topic " + topic);
|
||||
}
|
||||
|
||||
Session session1 = receivingConn.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
MessageConsumer goodConsumer = session1.createConsumer(topic);
|
||||
|
||||
TextMessage msg = session.createTextMessage("hello-world-2");
|
||||
producer.send(msg);
|
||||
|
||||
TextMessage receivedMsg = (TextMessage) goodConsumer.receive(2000);
|
||||
if (receivedMsg != null) {
|
||||
System.out.println("User " + user + " can send message [" + receivedMsg.getText() + "] to topic " + topic);
|
||||
}
|
||||
else {
|
||||
throw new IllegalStateException("Security setting is broken! User " + user +
|
||||
" cannot send message [" +
|
||||
msg.getText() +
|
||||
"] to topic " +
|
||||
topic);
|
||||
}
|
||||
|
||||
session.close();
|
||||
session1.close();
|
||||
}
|
||||
|
||||
// Check the user has neither send nor receive permission on topic
|
||||
private static void checkUserNoSendNoReceive(final Topic topic,
|
||||
final Connection connection,
|
||||
final String user) throws JMSException {
|
||||
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
MessageProducer producer = session.createProducer(topic);
|
||||
|
||||
try {
|
||||
session.createConsumer(topic);
|
||||
}
|
||||
catch (JMSException e) {
|
||||
System.out.println("User " + user + " cannot create consumer on topic " + topic);
|
||||
}
|
||||
|
||||
TextMessage msg = session.createTextMessage("hello-world-3");
|
||||
try {
|
||||
producer.send(msg);
|
||||
throw new IllegalStateException("Security setting is broken! User " + user +
|
||||
" can send message [" +
|
||||
msg.getText() +
|
||||
"] to topic " +
|
||||
topic);
|
||||
}
|
||||
catch (JMSException e) {
|
||||
System.out.println("User " + user + " cannot send message [" + msg.getText() + "] to topic: " + topic);
|
||||
}
|
||||
|
||||
session.close();
|
||||
}
|
||||
|
||||
// Check the user connection has both send and receive permissions on the topic
|
||||
private static void checkUserSendAndReceive(final Topic topic,
|
||||
final Connection connection,
|
||||
final String user) throws JMSException {
|
||||
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
TextMessage msg = session.createTextMessage("hello-world-4");
|
||||
MessageProducer producer = session.createProducer(topic);
|
||||
MessageConsumer consumer = session.createConsumer(topic);
|
||||
producer.send(msg);
|
||||
TextMessage receivedMsg = (TextMessage) consumer.receive(5000);
|
||||
if (receivedMsg != null) {
|
||||
System.out.println("User " + user + " can send message: [" + msg.getText() + "] to topic: " + topic);
|
||||
System.out.println("User " + user + " can receive message: [" + msg.getText() + "] from topic: " + topic);
|
||||
}
|
||||
else {
|
||||
throw new IllegalStateException("Error! User " + user + " cannot receive the message! ");
|
||||
}
|
||||
session.close();
|
||||
}
|
||||
|
||||
private static Connection createConnection(final String username,
|
||||
final String password,
|
||||
final ConnectionFactory cf) throws JMSException {
|
||||
return cf.createConnection(username, password);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,168 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
package org.apache.activemq.artemis.jms.example.ldap;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
import net.sf.ehcache.CacheManager;
|
||||
import net.sf.ehcache.config.CacheConfiguration;
|
||||
import net.sf.ehcache.config.Configuration;
|
||||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.directory.api.ldap.model.constants.SchemaConstants;
|
||||
import org.apache.directory.api.ldap.model.schema.LdapComparator;
|
||||
import org.apache.directory.api.ldap.model.schema.SchemaManager;
|
||||
import org.apache.directory.api.ldap.model.schema.comparators.NormalizingComparator;
|
||||
import org.apache.directory.api.ldap.model.schema.registries.ComparatorRegistry;
|
||||
import org.apache.directory.api.ldap.model.schema.registries.SchemaLoader;
|
||||
import org.apache.directory.api.ldap.schema.loader.JarLdifSchemaLoader;
|
||||
import org.apache.directory.api.ldap.schema.manager.impl.DefaultSchemaManager;
|
||||
import org.apache.directory.api.util.exception.Exceptions;
|
||||
import org.apache.directory.server.constants.ServerDNConstants;
|
||||
import org.apache.directory.server.core.DefaultDirectoryService;
|
||||
import org.apache.directory.server.core.api.CacheService;
|
||||
import org.apache.directory.server.core.api.DirectoryService;
|
||||
import org.apache.directory.server.core.api.InstanceLayout;
|
||||
import org.apache.directory.server.core.api.partition.Partition;
|
||||
import org.apache.directory.server.core.api.schema.SchemaPartition;
|
||||
import org.apache.directory.server.core.factory.AvlPartitionFactory;
|
||||
import org.apache.directory.server.core.factory.DirectoryServiceFactory;
|
||||
import org.apache.directory.server.core.factory.PartitionFactory;
|
||||
import org.apache.directory.server.i18n.I18n;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Factory for a fast (mostly in-memory-only) ApacheDS DirectoryService. Use only for tests!!
|
||||
*/
|
||||
public class InMemoryDirectoryServiceFactory implements DirectoryServiceFactory {
|
||||
|
||||
private static Logger LOG = LoggerFactory.getLogger(InMemoryDirectoryServiceFactory.class);
|
||||
|
||||
private final DirectoryService directoryService;
|
||||
private final PartitionFactory partitionFactory;
|
||||
|
||||
/**
|
||||
* Default constructor which creates {@link DefaultDirectoryService} instance and configures {@link AvlPartitionFactory} as
|
||||
* the {@link PartitionFactory} implementation.
|
||||
*/
|
||||
public InMemoryDirectoryServiceFactory() {
|
||||
try {
|
||||
directoryService = new DefaultDirectoryService();
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
directoryService.setShutdownHookEnabled(false);
|
||||
partitionFactory = new AvlPartitionFactory();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor which uses provided {@link DirectoryService} and {@link PartitionFactory} implementations.
|
||||
*
|
||||
* @param directoryService must be not-<code>null</code>
|
||||
* @param partitionFactory must be not-<code>null</code>
|
||||
*/
|
||||
public InMemoryDirectoryServiceFactory(DirectoryService directoryService, PartitionFactory partitionFactory) {
|
||||
this.directoryService = directoryService;
|
||||
this.partitionFactory = partitionFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void init(String name) throws Exception {
|
||||
if ((directoryService != null) && directoryService.isStarted()) {
|
||||
return;
|
||||
}
|
||||
|
||||
directoryService.setInstanceId(name);
|
||||
|
||||
// instance layout
|
||||
InstanceLayout instanceLayout = new InstanceLayout(System.getProperty("java.io.tmpdir") + "/server-work-" + name);
|
||||
if (instanceLayout.getInstanceDirectory().exists()) {
|
||||
try {
|
||||
FileUtils.deleteDirectory(instanceLayout.getInstanceDirectory());
|
||||
}
|
||||
catch (IOException e) {
|
||||
LOG.warn("couldn't delete the instance directory before initializing the DirectoryService", e);
|
||||
}
|
||||
}
|
||||
directoryService.setInstanceLayout(instanceLayout);
|
||||
|
||||
// EhCache in disabled-like-mode
|
||||
Configuration ehCacheConfig = new Configuration();
|
||||
CacheConfiguration defaultCache = new CacheConfiguration("default", 1)
|
||||
.eternal(false)
|
||||
.timeToIdleSeconds(30)
|
||||
.timeToLiveSeconds(30)
|
||||
.overflowToDisk(false);
|
||||
ehCacheConfig.addDefaultCache(defaultCache);
|
||||
CacheService cacheService = new CacheService(new CacheManager(ehCacheConfig));
|
||||
directoryService.setCacheService(cacheService);
|
||||
|
||||
// Init the schema
|
||||
// SchemaLoader loader = new SingleLdifSchemaLoader();
|
||||
SchemaLoader loader = new JarLdifSchemaLoader();
|
||||
SchemaManager schemaManager = new DefaultSchemaManager(loader);
|
||||
schemaManager.loadAllEnabled();
|
||||
ComparatorRegistry comparatorRegistry = schemaManager.getComparatorRegistry();
|
||||
for (LdapComparator<?> comparator : comparatorRegistry) {
|
||||
if (comparator instanceof NormalizingComparator) {
|
||||
((NormalizingComparator) comparator).setOnServer();
|
||||
}
|
||||
}
|
||||
directoryService.setSchemaManager(schemaManager);
|
||||
InMemorySchemaPartition inMemorySchemaPartition = new InMemorySchemaPartition(schemaManager);
|
||||
|
||||
SchemaPartition schemaPartition = new SchemaPartition(schemaManager);
|
||||
schemaPartition.setWrappedPartition(inMemorySchemaPartition);
|
||||
directoryService.setSchemaPartition(schemaPartition);
|
||||
List<Throwable> errors = schemaManager.getErrors();
|
||||
if (errors.size() != 0) {
|
||||
throw new Exception(I18n.err(I18n.ERR_317, Exceptions.printErrors(errors)));
|
||||
}
|
||||
|
||||
// Init system partition
|
||||
Partition systemPartition = partitionFactory.createPartition(directoryService.getSchemaManager(), directoryService
|
||||
.getDnFactory(), "system", ServerDNConstants.SYSTEM_DN, 500, new File(directoryService
|
||||
.getInstanceLayout()
|
||||
.getPartitionsDirectory(), "system"));
|
||||
systemPartition.setSchemaManager(directoryService.getSchemaManager());
|
||||
partitionFactory.addIndex(systemPartition, SchemaConstants.OBJECT_CLASS_AT, 100);
|
||||
directoryService.setSystemPartition(systemPartition);
|
||||
|
||||
directoryService.startup();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public DirectoryService getDirectoryService() throws Exception {
|
||||
return directoryService;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public PartitionFactory getPartitionFactory() throws Exception {
|
||||
return partitionFactory;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
package org.apache.activemq.artemis.jms.example.ldap;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.Map;
|
||||
import java.util.TreeSet;
|
||||
import java.util.UUID;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import javax.naming.InvalidNameException;
|
||||
|
||||
import org.apache.directory.api.ldap.model.constants.SchemaConstants;
|
||||
import org.apache.directory.api.ldap.model.entry.DefaultEntry;
|
||||
import org.apache.directory.api.ldap.model.entry.Entry;
|
||||
import org.apache.directory.api.ldap.model.ldif.LdifEntry;
|
||||
import org.apache.directory.api.ldap.model.ldif.LdifReader;
|
||||
import org.apache.directory.api.ldap.model.schema.SchemaManager;
|
||||
import org.apache.directory.api.ldap.schema.extractor.impl.DefaultSchemaLdifExtractor;
|
||||
import org.apache.directory.api.ldap.schema.extractor.impl.ResourceMap;
|
||||
import org.apache.directory.server.core.api.interceptor.context.AddOperationContext;
|
||||
import org.apache.directory.server.core.partition.ldif.AbstractLdifPartition;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* In-memory schema-only partition which loads the data in the similar way as the
|
||||
* {@link org.apache.directory.api.ldap.schema.loader.JarLdifSchemaLoader}.
|
||||
*/
|
||||
public class InMemorySchemaPartition extends AbstractLdifPartition {
|
||||
|
||||
private static Logger LOG = LoggerFactory.getLogger(InMemorySchemaPartition.class);
|
||||
|
||||
/**
|
||||
* Filesystem path separator pattern, either forward slash or backslash. java.util.regex.Pattern is immutable so only one
|
||||
* instance is needed for all uses.
|
||||
*/
|
||||
|
||||
public InMemorySchemaPartition(SchemaManager schemaManager) {
|
||||
super(schemaManager);
|
||||
}
|
||||
|
||||
/**
|
||||
* Partition initialization - loads schema entries from the files on classpath.
|
||||
*
|
||||
* @see org.apache.directory.server.core.partition.impl.avl.AvlPartition#doInit()
|
||||
*/
|
||||
@Override
|
||||
protected void doInit() throws InvalidNameException, Exception {
|
||||
if (initialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
LOG.debug("Initializing schema partition " + getId());
|
||||
suffixDn.apply(schemaManager);
|
||||
super.doInit();
|
||||
|
||||
// load schema
|
||||
final Map<String, Boolean> resMap = ResourceMap.getResources(Pattern.compile("schema[/\\Q\\\\E]ou=schema.*"));
|
||||
for (String resourcePath : new TreeSet<String>(resMap.keySet())) {
|
||||
if (resourcePath.endsWith(".ldif")) {
|
||||
URL resource = DefaultSchemaLdifExtractor.getUniqueResource(resourcePath, "Schema LDIF file");
|
||||
LdifReader reader = new LdifReader(resource.openStream());
|
||||
LdifEntry ldifEntry = reader.next();
|
||||
reader.close();
|
||||
|
||||
Entry entry = new DefaultEntry(schemaManager, ldifEntry.getEntry());
|
||||
// add mandatory attributes
|
||||
if (entry.get(SchemaConstants.ENTRY_CSN_AT) == null) {
|
||||
entry.add(SchemaConstants.ENTRY_CSN_AT, defaultCSNFactory.newInstance().toString());
|
||||
}
|
||||
if (entry.get(SchemaConstants.ENTRY_UUID_AT) == null) {
|
||||
entry.add(SchemaConstants.ENTRY_UUID_AT, UUID.randomUUID().toString());
|
||||
}
|
||||
AddOperationContext addContext = new AddOperationContext(null, entry);
|
||||
super.add(addContext);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,102 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
package org.apache.activemq.artemis.jms.example.ldap;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.apache.directory.api.ldap.model.entry.DefaultEntry;
|
||||
import org.apache.directory.api.ldap.model.ldif.LdifEntry;
|
||||
import org.apache.directory.api.ldap.model.ldif.LdifReader;
|
||||
import org.apache.directory.api.ldap.model.name.Dn;
|
||||
import org.apache.directory.api.ldap.model.schema.SchemaManager;
|
||||
import org.apache.directory.server.core.api.DirectoryService;
|
||||
import org.apache.directory.server.core.partition.impl.avl.AvlPartition;
|
||||
import org.apache.directory.server.protocol.shared.transport.TcpTransport;
|
||||
|
||||
/**
|
||||
* Creates and starts LDAP server(s).
|
||||
*/
|
||||
public class LdapServer {
|
||||
|
||||
private final DirectoryService directoryService;
|
||||
private final org.apache.directory.server.ldap.LdapServer ldapServer;
|
||||
|
||||
/**
|
||||
* Create a single LDAP server.
|
||||
*
|
||||
* @param ldifFile
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public LdapServer(String ldifFile) throws Exception {
|
||||
InMemoryDirectoryServiceFactory dsFactory = new InMemoryDirectoryServiceFactory();
|
||||
dsFactory.init("ds");
|
||||
|
||||
directoryService = dsFactory.getDirectoryService();
|
||||
|
||||
final SchemaManager schemaManager = directoryService.getSchemaManager();
|
||||
importLdif(directoryService, schemaManager, new LdifReader(ldifFile));
|
||||
|
||||
ldapServer = new org.apache.directory.server.ldap.LdapServer();
|
||||
ldapServer.setTransports(new TcpTransport("127.0.0.1", 1024));
|
||||
ldapServer.setDirectoryService(directoryService);
|
||||
|
||||
ldapServer.start();
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops LDAP server and the underlying directory service.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public void stop() throws Exception {
|
||||
ldapServer.stop();
|
||||
directoryService.shutdown();
|
||||
}
|
||||
|
||||
private void importLdif(DirectoryService directoryService, final SchemaManager schemaManager, LdifReader ldifReader) throws Exception {
|
||||
try {
|
||||
for (LdifEntry ldifEntry : ldifReader) {
|
||||
checkPartition(ldifEntry);
|
||||
directoryService.getAdminSession().add(new DefaultEntry(schemaManager, ldifEntry.getEntry()));
|
||||
}
|
||||
}
|
||||
finally {
|
||||
try {
|
||||
ldifReader.close();
|
||||
}
|
||||
catch (IOException ioe) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void checkPartition(LdifEntry ldifEntry) throws Exception {
|
||||
Dn dn = ldifEntry.getDn();
|
||||
Dn parent = dn.getParent();
|
||||
try {
|
||||
directoryService.getAdminSession().exists(parent);
|
||||
}
|
||||
catch (Exception e) {
|
||||
System.out.println("Creating new partition for DN=" + dn + "\n");
|
||||
AvlPartition partition = new AvlPartition(directoryService.getSchemaManager());
|
||||
partition.setId(dn.getName());
|
||||
partition.setSuffixDn(dn);
|
||||
directoryService.addPartition(partition);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
## ---------------------------------------------------------------------------
|
||||
## 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.
|
||||
## ---------------------------------------------------------------------------
|
||||
user=bill,andrew,frank,sam
|
||||
europe-user=andrew
|
||||
news-user=frank,sam
|
||||
us-user=frank
|
|
@ -0,0 +1,20 @@
|
|||
## ---------------------------------------------------------------------------
|
||||
## 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.
|
||||
## ---------------------------------------------------------------------------
|
||||
bill=activemq
|
||||
andrew=activemq1
|
||||
frank=activemq2
|
||||
sam=activemq3
|
|
@ -0,0 +1,84 @@
|
|||
<?xml version='1.0'?>
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
|
||||
<configuration xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="urn:activemq"
|
||||
xsi:schemaLocation="urn:activemq /schema/artemis-server.xsd">
|
||||
|
||||
<jms xmlns="urn:activemq:jms">
|
||||
<topic name="genericTopic"/>
|
||||
|
||||
<topic name="news.europe.europeTopic"/>
|
||||
|
||||
<topic name="news.us.usTopic"/>
|
||||
</jms>
|
||||
|
||||
<core xmlns="urn:activemq:core">
|
||||
|
||||
<bindings-directory>./data/messaging/bindings</bindings-directory>
|
||||
|
||||
<journal-directory>./data/messaging/journal</journal-directory>
|
||||
|
||||
<large-messages-directory>./data/messaging/largemessages</large-messages-directory>
|
||||
|
||||
<paging-directory>./data/messaging/paging</paging-directory>
|
||||
|
||||
<cluster-user>myClusterUser</cluster-user>
|
||||
<cluster-password>myClusterPassword</cluster-password>
|
||||
|
||||
<!-- Acceptors -->
|
||||
<acceptors>
|
||||
<acceptor name="netty-acceptor">tcp://localhost:61616</acceptor>
|
||||
</acceptors>
|
||||
|
||||
<!-- Other config -->
|
||||
|
||||
<security-settings>
|
||||
<!-- any user can have full control of generic topics -->
|
||||
<security-setting match="jms.topic.#">
|
||||
<permission type="createDurableQueue" roles="user"/>
|
||||
<permission type="deleteDurableQueue" roles="user"/>
|
||||
<permission type="createNonDurableQueue" roles="user"/>
|
||||
<permission type="deleteNonDurableQueue" roles="user"/>
|
||||
<permission type="send" roles="user"/>
|
||||
<permission type="consume" roles="user"/>
|
||||
</security-setting>
|
||||
|
||||
<security-setting match="jms.topic.news.europe.#">
|
||||
<permission type="createDurableQueue" roles="user"/>
|
||||
<permission type="deleteDurableQueue" roles="user"/>
|
||||
<permission type="createNonDurableQueue" roles="user"/>
|
||||
<permission type="deleteNonDurableQueue" roles="user"/>
|
||||
<permission type="send" roles="europe-user"/>
|
||||
<permission type="consume" roles="news-user"/>
|
||||
</security-setting>
|
||||
|
||||
<security-setting match="jms.topic.news.us.#">
|
||||
<permission type="createDurableQueue" roles="user"/>
|
||||
<permission type="deleteDurableQueue" roles="user"/>
|
||||
<permission type="createNonDurableQueue" roles="user"/>
|
||||
<permission type="deleteNonDurableQueue" roles="user"/>
|
||||
<permission type="send" roles="us-user"/>
|
||||
<permission type="consume" roles="news-user"/>
|
||||
</security-setting>
|
||||
</security-settings>
|
||||
|
||||
</core>
|
||||
</configuration>
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
activemq {
|
||||
org.apache.activemq.artemis.spi.core.security.jaas.LDAPLoginModule required
|
||||
debug=true
|
||||
initialContextFactory=com.sun.jndi.ldap.LdapCtxFactory
|
||||
connectionURL="ldap://localhost:1024"
|
||||
connectionUsername="uid=admin,ou=system"
|
||||
connectionPassword=secret
|
||||
connectionProtocol=s
|
||||
authentication=simple
|
||||
userBase="dc=activemq,dc=org"
|
||||
userSearchMatching="(uid={0})"
|
||||
userSearchSubtree=false
|
||||
roleBase="dc=activemq,dc=org"
|
||||
roleName=cn
|
||||
roleSearchMatching="(member=uid={1},dc=activemq,dc=org)"
|
||||
roleSearchSubtree=false
|
||||
;
|
||||
};
|
|
@ -0,0 +1,81 @@
|
|||
## ---------------------------------------------------------------------------
|
||||
## 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.
|
||||
## ---------------------------------------------------------------------------
|
||||
|
||||
dn: dc=activemq,dc=org
|
||||
dc: activemq
|
||||
objectClass: top
|
||||
objectClass: domain
|
||||
|
||||
dn: uid=bill,dc=activemq,dc=org
|
||||
uid: bill
|
||||
userPassword: activemq
|
||||
objectClass: account
|
||||
objectClass: simpleSecurityObject
|
||||
objectClass: top
|
||||
|
||||
dn: uid=andrew,dc=activemq,dc=org
|
||||
uid: andrew
|
||||
userPassword: activemq1
|
||||
objectClass: account
|
||||
objectClass: simpleSecurityObject
|
||||
objectClass: top
|
||||
|
||||
dn: uid=frank,dc=activemq,dc=org
|
||||
uid: frank
|
||||
userPassword: activemq2
|
||||
objectClass: account
|
||||
objectClass: simpleSecurityObject
|
||||
objectClass: top
|
||||
|
||||
dn: uid=sam,dc=activemq,dc=org
|
||||
uid: sam
|
||||
userPassword: activemq3
|
||||
objectClass: account
|
||||
objectClass: simpleSecurityObject
|
||||
objectClass: top
|
||||
|
||||
###################
|
||||
## Define groups ##
|
||||
###################
|
||||
|
||||
dn: cn=user,dc=activemq,dc=org
|
||||
cn: user
|
||||
member: uid=bill,dc=activemq,dc=org
|
||||
member: uid=andrew,dc=activemq,dc=org
|
||||
member: uid=frank,dc=activemq,dc=org
|
||||
member: uid=sam,dc=activemq,dc=org
|
||||
objectClass: groupOfNames
|
||||
objectClass: top
|
||||
|
||||
dn: cn=europe-user,dc=activemq,dc=org
|
||||
cn: europe-user
|
||||
member: uid=andrew,dc=activemq,dc=org
|
||||
objectClass: groupOfNames
|
||||
objectClass: top
|
||||
|
||||
dn: cn=news-user,dc=activemq,dc=org
|
||||
cn: news-user
|
||||
member: uid=frank,dc=activemq,dc=org
|
||||
member: uid=sam,dc=activemq,dc=org
|
||||
objectClass: groupOfNames
|
||||
objectClass: top
|
||||
|
||||
dn: cn=us-user,dc=activemq,dc=org
|
||||
cn: us-user
|
||||
member: uid=frank,dc=activemq,dc=org
|
||||
objectClass: groupOfNames
|
||||
objectClass: top
|
|
@ -0,0 +1,22 @@
|
|||
# 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.
|
||||
|
||||
java.naming.factory.initial=org.apache.activemq.artemis.jndi.ActiveMQInitialContextFactory
|
||||
connectionFactory.ConnectionFactory=tcp://localhost:61616
|
||||
topic.topic/genericTopic=genericTopic
|
||||
topic.topic/europeTopic=news.europe.europeTopic
|
||||
topic.topic/usTopic=news.us.usTopic
|
Loading…
Reference in New Issue