ARTEMIS-308 security+LDAP example
Project: http://git-wip-us.apache.org/repos/asf/activemq-artemis/repo Commit: http://git-wip-us.apache.org/repos/asf/activemq-artemis/commit/dd4a8d68 Tree: http://git-wip-us.apache.org/repos/asf/activemq-artemis/tree/dd4a8d68 Diff: http://git-wip-us.apache.org/repos/asf/activemq-artemis/diff/dd4a8d68 Branch: refs/heads/master Commit: dd4a8d6879009487e30c843933043cca19f9786c Parents: 9cae390 Author: jbertram <[email protected]> Authored: Wed Dec 9 15:20:35 2015 -0600 Committer: jbertram <[email protected]> Committed: Wed Dec 16 16:01:48 2015 -0600 ---------------------------------------------------------------------- examples/features/standard/pom.xml | 3 +- .../features/standard/security-ldap/pom.xml | 151 +++++++++ .../features/standard/security-ldap/readme.html | 326 +++++++++++++++++++ .../artemis/jms/example/SecurityExample.java | 288 ++++++++++++++++ .../ldap/InMemoryDirectoryServiceFactory.java | 168 ++++++++++ .../example/ldap/InMemorySchemaPartition.java | 95 ++++++ .../artemis/jms/example/ldap/LdapServer.java | 102 ++++++ .../activemq/server0/artemis-roles.properties | 20 ++ .../activemq/server0/artemis-users.properties | 20 ++ .../main/resources/activemq/server0/broker.xml | 84 +++++ .../resources/activemq/server0/login.config | 35 ++ .../src/main/resources/example.ldif | 81 +++++ .../src/main/resources/jndi.properties | 22 ++ 13 files changed, 1394 insertions(+), 1 deletion(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/dd4a8d68/examples/features/standard/pom.xml ---------------------------------------------------------------------- diff --git a/examples/features/standard/pom.xml b/examples/features/standard/pom.xml index d900cb6..c9edfcc 100644 --- a/examples/features/standard/pom.xml +++ b/examples/features/standard/pom.xml @@ -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> http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/dd4a8d68/examples/features/standard/security-ldap/pom.xml ---------------------------------------------------------------------- diff --git a/examples/features/standard/security-ldap/pom.xml b/examples/features/standard/security-ldap/pom.xml new file mode 100644 index 0000000..316c9c9 --- /dev/null +++ b/examples/features/standard/security-ldap/pom.xml @@ -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> http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/dd4a8d68/examples/features/standard/security-ldap/readme.html ---------------------------------------------------------------------- diff --git a/examples/features/standard/security-ldap/readme.html b/examples/features/standard/security-ldap/readme.html new file mode 100644 index 0000000..fad945a --- /dev/null +++ b/examples/features/standard/security-ldap/readme.html @@ -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> http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/dd4a8d68/examples/features/standard/security-ldap/src/main/java/org/apache/activemq/artemis/jms/example/SecurityExample.java ---------------------------------------------------------------------- diff --git a/examples/features/standard/security-ldap/src/main/java/org/apache/activemq/artemis/jms/example/SecurityExample.java b/examples/features/standard/security-ldap/src/main/java/org/apache/activemq/artemis/jms/example/SecurityExample.java new file mode 100644 index 0000000..94f4b43 --- /dev/null +++ b/examples/features/standard/security-ldap/src/main/java/org/apache/activemq/artemis/jms/example/SecurityExample.java @@ -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); + } +} http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/dd4a8d68/examples/features/standard/security-ldap/src/main/java/org/apache/activemq/artemis/jms/example/ldap/InMemoryDirectoryServiceFactory.java ---------------------------------------------------------------------- diff --git a/examples/features/standard/security-ldap/src/main/java/org/apache/activemq/artemis/jms/example/ldap/InMemoryDirectoryServiceFactory.java b/examples/features/standard/security-ldap/src/main/java/org/apache/activemq/artemis/jms/example/ldap/InMemoryDirectoryServiceFactory.java new file mode 100644 index 0000000..61bf77e --- /dev/null +++ b/examples/features/standard/security-ldap/src/main/java/org/apache/activemq/artemis/jms/example/ldap/InMemoryDirectoryServiceFactory.java @@ -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; + } + +} http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/dd4a8d68/examples/features/standard/security-ldap/src/main/java/org/apache/activemq/artemis/jms/example/ldap/InMemorySchemaPartition.java ---------------------------------------------------------------------- diff --git a/examples/features/standard/security-ldap/src/main/java/org/apache/activemq/artemis/jms/example/ldap/InMemorySchemaPartition.java b/examples/features/standard/security-ldap/src/main/java/org/apache/activemq/artemis/jms/example/ldap/InMemorySchemaPartition.java new file mode 100644 index 0000000..b7bb1f7 --- /dev/null +++ b/examples/features/standard/security-ldap/src/main/java/org/apache/activemq/artemis/jms/example/ldap/InMemorySchemaPartition.java @@ -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); + } + } + } + +} http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/dd4a8d68/examples/features/standard/security-ldap/src/main/java/org/apache/activemq/artemis/jms/example/ldap/LdapServer.java ---------------------------------------------------------------------- diff --git a/examples/features/standard/security-ldap/src/main/java/org/apache/activemq/artemis/jms/example/ldap/LdapServer.java b/examples/features/standard/security-ldap/src/main/java/org/apache/activemq/artemis/jms/example/ldap/LdapServer.java new file mode 100644 index 0000000..1161922 --- /dev/null +++ b/examples/features/standard/security-ldap/src/main/java/org/apache/activemq/artemis/jms/example/ldap/LdapServer.java @@ -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); + } + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/dd4a8d68/examples/features/standard/security-ldap/src/main/resources/activemq/server0/artemis-roles.properties ---------------------------------------------------------------------- diff --git a/examples/features/standard/security-ldap/src/main/resources/activemq/server0/artemis-roles.properties b/examples/features/standard/security-ldap/src/main/resources/activemq/server0/artemis-roles.properties new file mode 100644 index 0000000..71e672d --- /dev/null +++ b/examples/features/standard/security-ldap/src/main/resources/activemq/server0/artemis-roles.properties @@ -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 \ No newline at end of file http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/dd4a8d68/examples/features/standard/security-ldap/src/main/resources/activemq/server0/artemis-users.properties ---------------------------------------------------------------------- diff --git a/examples/features/standard/security-ldap/src/main/resources/activemq/server0/artemis-users.properties b/examples/features/standard/security-ldap/src/main/resources/activemq/server0/artemis-users.properties new file mode 100644 index 0000000..0a206c6 --- /dev/null +++ b/examples/features/standard/security-ldap/src/main/resources/activemq/server0/artemis-users.properties @@ -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 \ No newline at end of file http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/dd4a8d68/examples/features/standard/security-ldap/src/main/resources/activemq/server0/broker.xml ---------------------------------------------------------------------- diff --git a/examples/features/standard/security-ldap/src/main/resources/activemq/server0/broker.xml b/examples/features/standard/security-ldap/src/main/resources/activemq/server0/broker.xml new file mode 100644 index 0000000..667ac95 --- /dev/null +++ b/examples/features/standard/security-ldap/src/main/resources/activemq/server0/broker.xml @@ -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> http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/dd4a8d68/examples/features/standard/security-ldap/src/main/resources/activemq/server0/login.config ---------------------------------------------------------------------- diff --git a/examples/features/standard/security-ldap/src/main/resources/activemq/server0/login.config b/examples/features/standard/security-ldap/src/main/resources/activemq/server0/login.config new file mode 100644 index 0000000..90fb445 --- /dev/null +++ b/examples/features/standard/security-ldap/src/main/resources/activemq/server0/login.config @@ -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 + ; +}; \ No newline at end of file http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/dd4a8d68/examples/features/standard/security-ldap/src/main/resources/example.ldif ---------------------------------------------------------------------- diff --git a/examples/features/standard/security-ldap/src/main/resources/example.ldif b/examples/features/standard/security-ldap/src/main/resources/example.ldif new file mode 100644 index 0000000..da135da --- /dev/null +++ b/examples/features/standard/security-ldap/src/main/resources/example.ldif @@ -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 \ No newline at end of file http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/dd4a8d68/examples/features/standard/security-ldap/src/main/resources/jndi.properties ---------------------------------------------------------------------- diff --git a/examples/features/standard/security-ldap/src/main/resources/jndi.properties b/examples/features/standard/security-ldap/src/main/resources/jndi.properties new file mode 100644 index 0000000..0a3b640 --- /dev/null +++ b/examples/features/standard/security-ldap/src/main/resources/jndi.properties @@ -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
