mirror of https://github.com/apache/activemq.git
https://issues.apache.org/jira/browse/AMQ-3851 - refactor AuthorizationBroker so that addDestinationInfo is properly handled
git-svn-id: https://svn.apache.org/repos/asf/activemq/trunk@1393988 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
e7137b7eae
commit
205699e11e
|
@ -46,22 +46,18 @@ public class AuthorizationBroker extends BrokerFilter implements SecurityAdminMB
|
|||
this.authorizationMap = authorizationMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addDestinationInfo(ConnectionContext context, DestinationInfo info) throws Exception {
|
||||
addDestination(context, info.getDestination(),true);
|
||||
super.addDestinationInfo(context, info);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Destination addDestination(ConnectionContext context, ActiveMQDestination destination,boolean create) throws Exception {
|
||||
protected SecurityContext checkSecurityContext(ConnectionContext context) throws SecurityException {
|
||||
final SecurityContext securityContext = context.getSecurityContext();
|
||||
if (securityContext == null) {
|
||||
throw new SecurityException("User is not authenticated.");
|
||||
}
|
||||
return securityContext;
|
||||
}
|
||||
|
||||
protected boolean checkDestinationAdmin(SecurityContext securityContext, ActiveMQDestination destination) {
|
||||
Destination existing = this.getDestinationMap().get(destination);
|
||||
if (existing != null) {
|
||||
return super.addDestination(context, destination,create);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!securityContext.isBrokerContext()) {
|
||||
|
@ -73,9 +69,29 @@ public class AuthorizationBroker extends BrokerFilter implements SecurityAdminMB
|
|||
}
|
||||
|
||||
if (allowedACLs != null && !securityContext.isInOneOf(allowedACLs)) {
|
||||
throw new SecurityException("User " + securityContext.getUserName() + " is not authorized to create: " + destination);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addDestinationInfo(ConnectionContext context, DestinationInfo info) throws Exception {
|
||||
final SecurityContext securityContext = checkSecurityContext(context);
|
||||
|
||||
if (!checkDestinationAdmin(securityContext, info.getDestination())) {
|
||||
throw new SecurityException("User " + securityContext.getUserName() + " is not authorized to create: " + info.getDestination());
|
||||
}
|
||||
|
||||
super.addDestinationInfo(context, info);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Destination addDestination(ConnectionContext context, ActiveMQDestination destination,boolean create) throws Exception {
|
||||
final SecurityContext securityContext = checkSecurityContext(context);
|
||||
|
||||
if (!checkDestinationAdmin(securityContext, destination)) {
|
||||
throw new SecurityException("User " + securityContext.getUserName() + " is not authorized to create: " + destination);
|
||||
}
|
||||
|
||||
return super.addDestination(context, destination,create);
|
||||
|
@ -83,31 +99,30 @@ public class AuthorizationBroker extends BrokerFilter implements SecurityAdminMB
|
|||
|
||||
@Override
|
||||
public void removeDestination(ConnectionContext context, ActiveMQDestination destination, long timeout) throws Exception {
|
||||
final SecurityContext securityContext = checkSecurityContext(context);
|
||||
|
||||
final SecurityContext securityContext = context.getSecurityContext();
|
||||
if (securityContext == null) {
|
||||
throw new SecurityException("User is not authenticated.");
|
||||
}
|
||||
Set<?> allowedACLs = null;
|
||||
if (!destination.isTemporary()) {
|
||||
allowedACLs = authorizationMap.getAdminACLs(destination);
|
||||
} else {
|
||||
allowedACLs = authorizationMap.getTempDestinationAdminACLs();
|
||||
}
|
||||
|
||||
if (!securityContext.isBrokerContext() && allowedACLs != null && !securityContext.isInOneOf(allowedACLs)) {
|
||||
if (!checkDestinationAdmin(securityContext, destination)) {
|
||||
throw new SecurityException("User " + securityContext.getUserName() + " is not authorized to remove: " + destination);
|
||||
}
|
||||
|
||||
super.removeDestination(context, destination, timeout);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Subscription addConsumer(ConnectionContext context, ConsumerInfo info) throws Exception {
|
||||
public void removeDestinationInfo(ConnectionContext context, DestinationInfo info) throws Exception {
|
||||
final SecurityContext securityContext = checkSecurityContext(context);
|
||||
|
||||
final SecurityContext subject = context.getSecurityContext();
|
||||
if (subject == null) {
|
||||
throw new SecurityException("User is not authenticated.");
|
||||
if (!checkDestinationAdmin(securityContext, info.getDestination())) {
|
||||
throw new SecurityException("User " + securityContext.getUserName() + " is not authorized to remove: " + info.getDestination());
|
||||
}
|
||||
|
||||
super.removeDestinationInfo(context, info);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Subscription addConsumer(ConnectionContext context, ConsumerInfo info) throws Exception {
|
||||
final SecurityContext securityContext = checkSecurityContext(context);
|
||||
|
||||
Set<?> allowedACLs = null;
|
||||
if (!info.getDestination().isTemporary()) {
|
||||
allowedACLs = authorizationMap.getReadACLs(info.getDestination());
|
||||
|
@ -115,10 +130,10 @@ public class AuthorizationBroker extends BrokerFilter implements SecurityAdminMB
|
|||
allowedACLs = authorizationMap.getTempDestinationReadACLs();
|
||||
}
|
||||
|
||||
if (!subject.isBrokerContext() && allowedACLs != null && !subject.isInOneOf(allowedACLs)) {
|
||||
throw new SecurityException("User " + subject.getUserName() + " is not authorized to read from: " + info.getDestination());
|
||||
if (!securityContext.isBrokerContext() && allowedACLs != null && !securityContext.isInOneOf(allowedACLs)) {
|
||||
throw new SecurityException("User " + securityContext.getUserName() + " is not authorized to read from: " + info.getDestination());
|
||||
}
|
||||
subject.getAuthorizedReadDests().put(info.getDestination(), info.getDestination());
|
||||
securityContext.getAuthorizedReadDests().put(info.getDestination(), info.getDestination());
|
||||
|
||||
/*
|
||||
* Need to think about this a little more. We could do per message
|
||||
|
@ -146,12 +161,9 @@ public class AuthorizationBroker extends BrokerFilter implements SecurityAdminMB
|
|||
|
||||
@Override
|
||||
public void addProducer(ConnectionContext context, ProducerInfo info) throws Exception {
|
||||
final SecurityContext securityContext = checkSecurityContext(context);
|
||||
|
||||
SecurityContext subject = context.getSecurityContext();
|
||||
if (subject == null) {
|
||||
throw new SecurityException("User is not authenticated.");
|
||||
}
|
||||
if (!subject.isBrokerContext() && info.getDestination() != null) {
|
||||
if (!securityContext.isBrokerContext() && info.getDestination() != null) {
|
||||
|
||||
Set<?> allowedACLs = null;
|
||||
if (!info.getDestination().isTemporary()) {
|
||||
|
@ -159,10 +171,10 @@ public class AuthorizationBroker extends BrokerFilter implements SecurityAdminMB
|
|||
} else {
|
||||
allowedACLs = authorizationMap.getTempDestinationWriteACLs();
|
||||
}
|
||||
if (allowedACLs != null && !subject.isInOneOf(allowedACLs)) {
|
||||
throw new SecurityException("User " + subject.getUserName() + " is not authorized to write to: " + info.getDestination());
|
||||
if (allowedACLs != null && !securityContext.isInOneOf(allowedACLs)) {
|
||||
throw new SecurityException("User " + securityContext.getUserName() + " is not authorized to write to: " + info.getDestination());
|
||||
}
|
||||
subject.getAuthorizedWriteDests().put(info.getDestination(), info.getDestination());
|
||||
securityContext.getAuthorizedWriteDests().put(info.getDestination(), info.getDestination());
|
||||
}
|
||||
|
||||
super.addProducer(context, info);
|
||||
|
@ -170,11 +182,9 @@ public class AuthorizationBroker extends BrokerFilter implements SecurityAdminMB
|
|||
|
||||
@Override
|
||||
public void send(ProducerBrokerExchange producerExchange, Message messageSend) throws Exception {
|
||||
SecurityContext subject = producerExchange.getConnectionContext().getSecurityContext();
|
||||
if (subject == null) {
|
||||
throw new SecurityException("User is not authenticated.");
|
||||
}
|
||||
if (!subject.isBrokerContext() && !subject.getAuthorizedWriteDests().contains(messageSend.getDestination())) {
|
||||
final SecurityContext securityContext = checkSecurityContext(producerExchange.getConnectionContext());
|
||||
|
||||
if (!securityContext.isBrokerContext() && !securityContext.getAuthorizedWriteDests().contains(messageSend.getDestination())) {
|
||||
|
||||
Set<?> allowedACLs = null;
|
||||
if (!messageSend.getDestination().isTemporary()) {
|
||||
|
@ -183,10 +193,10 @@ public class AuthorizationBroker extends BrokerFilter implements SecurityAdminMB
|
|||
allowedACLs = authorizationMap.getTempDestinationWriteACLs();
|
||||
}
|
||||
|
||||
if (allowedACLs != null && !subject.isInOneOf(allowedACLs)) {
|
||||
throw new SecurityException("User " + subject.getUserName() + " is not authorized to write to: " + messageSend.getDestination());
|
||||
if (allowedACLs != null && !securityContext.isInOneOf(allowedACLs)) {
|
||||
throw new SecurityException("User " + securityContext.getUserName() + " is not authorized to write to: " + messageSend.getDestination());
|
||||
}
|
||||
subject.getAuthorizedWriteDests().put(messageSend.getDestination(), messageSend.getDestination());
|
||||
securityContext.getAuthorizedWriteDests().put(messageSend.getDestination(), messageSend.getDestination());
|
||||
}
|
||||
|
||||
super.send(producerExchange, messageSend);
|
||||
|
|
|
@ -0,0 +1,89 @@
|
|||
/**
|
||||
* 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.usecases;
|
||||
|
||||
import org.apache.activemq.ActiveMQConnection;
|
||||
import org.apache.activemq.ActiveMQMessageConsumer;
|
||||
import org.apache.activemq.JmsMultipleBrokersTestSupport;
|
||||
import org.apache.activemq.command.ActiveMQQueue;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
|
||||
import javax.jms.ConnectionFactory;
|
||||
import javax.jms.MessageProducer;
|
||||
import javax.jms.Session;
|
||||
import javax.jms.TemporaryQueue;
|
||||
|
||||
public class TwoSecureBrokerRequestReplyTest extends JmsMultipleBrokersTestSupport {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(TwoSecureBrokerRequestReplyTest.class);
|
||||
|
||||
public void setUp() throws Exception {
|
||||
super.setAutoFail(true);
|
||||
super.setUp();
|
||||
|
||||
createBroker(new ClassPathResource("org/apache/activemq/usecases/sender-secured.xml"));
|
||||
createBroker(new ClassPathResource("org/apache/activemq/usecases/receiver-secured.xml"));
|
||||
}
|
||||
|
||||
public void testRequestReply() throws Exception {
|
||||
ActiveMQQueue requestReplyDest = new ActiveMQQueue("RequestReply");
|
||||
|
||||
startAllBrokers();
|
||||
waitForBridgeFormation();
|
||||
waitForMinTopicRegionConsumerCount("sender", 1);
|
||||
waitForMinTopicRegionConsumerCount("receiver", 1);
|
||||
|
||||
|
||||
ConnectionFactory factory = getConnectionFactory("sender");
|
||||
ActiveMQConnection conn = (ActiveMQConnection) factory.createConnection("system", "manager");
|
||||
conn.setWatchTopicAdvisories(false);
|
||||
conn.start();
|
||||
Session session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
|
||||
ConnectionFactory replyFactory = getConnectionFactory("receiver");
|
||||
for (int i = 0; i < 2000; i++) {
|
||||
TemporaryQueue tempDest = session.createTemporaryQueue();
|
||||
MessageProducer producer = session.createProducer(requestReplyDest);
|
||||
javax.jms.Message message = session.createTextMessage("req-" + i);
|
||||
message.setJMSReplyTo(tempDest);
|
||||
|
||||
ActiveMQMessageConsumer consumer = (ActiveMQMessageConsumer) session.createConsumer(tempDest);
|
||||
producer.send(message);
|
||||
|
||||
ActiveMQConnection replyConnection = (ActiveMQConnection) replyFactory.createConnection("system", "manager");
|
||||
replyConnection.setWatchTopicAdvisories(false);
|
||||
replyConnection.start();
|
||||
Session replySession = replyConnection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
ActiveMQMessageConsumer replyConsumer = (ActiveMQMessageConsumer) replySession.createConsumer(requestReplyDest);
|
||||
javax.jms.Message msg = replyConsumer.receive(10000);
|
||||
assertNotNull("request message not null: " + i, msg);
|
||||
MessageProducer replyProducer = replySession.createProducer(msg.getJMSReplyTo());
|
||||
replyProducer.send(session.createTextMessage("reply-" + i));
|
||||
replyConnection.close();
|
||||
|
||||
javax.jms.Message reply = consumer.receive(10000);
|
||||
assertNotNull("reply message : " + i + ", to: " + tempDest + ", by consumer:" + consumer.getConsumerId(), reply);
|
||||
consumer.close();
|
||||
tempDest.delete();
|
||||
LOG.info("message #" + i + " processed");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -76,7 +76,7 @@
|
|||
<authorizationEntry topic="ActiveMQ.Advisory.>" read="guests,users" write="guests,users" admin="guests,users"/>
|
||||
</authorizationEntries>
|
||||
<tempDestinationAuthorizationEntry>
|
||||
<tempDestinationAuthorizationEntry read="admin" write="admin" admin="admin"/>
|
||||
<tempDestinationAuthorizationEntry read="admins" write="admins" admin="admins"/>
|
||||
</tempDestinationAuthorizationEntry>
|
||||
</authorizationMap>
|
||||
</map>
|
||||
|
|
|
@ -0,0 +1,78 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
<beans
|
||||
xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:amq="http://activemq.apache.org/schema/core"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
|
||||
http://activemq.apache.org/schema/core http://activemq.apache.org/schema/core/activemq-core.xsd">
|
||||
|
||||
<broker brokerName="receiver" persistent="false" useJmx="true" allowTempAutoCreationOnSend="true" xmlns="http://activemq.apache.org/schema/core">
|
||||
|
||||
<networkConnectors>
|
||||
<networkConnector uri="static:(tcp://localhost:62001)" userName="system" password="manager"/>
|
||||
</networkConnectors>
|
||||
|
||||
<persistenceAdapter>
|
||||
<memoryPersistenceAdapter/>
|
||||
</persistenceAdapter>
|
||||
|
||||
<plugins>
|
||||
<simpleAuthenticationPlugin>
|
||||
<users>
|
||||
<authenticationUser username="system" password="manager"
|
||||
groups="users,admins"/>
|
||||
<authenticationUser username="user" password="user"
|
||||
groups="users"/>
|
||||
<authenticationUser username="guest" password="guest" groups="guests"/>
|
||||
</users>
|
||||
</simpleAuthenticationPlugin>
|
||||
|
||||
|
||||
<!-- lets configure a destination based authorization mechanism -->
|
||||
<authorizationPlugin>
|
||||
<map>
|
||||
<authorizationMap>
|
||||
<authorizationEntries>
|
||||
<authorizationEntry queue=">" read="admins" write="admins" admin="admins" />
|
||||
<authorizationEntry queue="USERS.>" read="users" write="users" admin="users" />
|
||||
<authorizationEntry queue="GUEST.>" read="guests" write="guests,users" admin="guests,users" />
|
||||
|
||||
<authorizationEntry queue="TEST.Q" read="guests" write="guests" />
|
||||
|
||||
<authorizationEntry topic=">" read="admins" write="admins" admin="admins" />
|
||||
<authorizationEntry topic="USERS.>" read="users" write="users" admin="users" />
|
||||
<authorizationEntry topic="GUEST.>" read="guests" write="guests,users" admin="guests,users" />
|
||||
|
||||
<authorizationEntry topic="ActiveMQ.Advisory.>" read="guests,users" write="guests,users" admin="guests,users"/>
|
||||
</authorizationEntries>
|
||||
<tempDestinationAuthorizationEntry>
|
||||
<tempDestinationAuthorizationEntry read="admins" write="admins" admin="admins"/>
|
||||
</tempDestinationAuthorizationEntry>
|
||||
</authorizationMap>
|
||||
</map>
|
||||
</authorizationPlugin>
|
||||
</plugins>
|
||||
|
||||
<transportConnectors>
|
||||
<transportConnector uri="tcp://localhost:62002"/>
|
||||
</transportConnectors>
|
||||
|
||||
</broker>
|
||||
|
||||
</beans>
|
|
@ -0,0 +1,82 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
<beans
|
||||
xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:amq="http://activemq.apache.org/schema/core"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
|
||||
http://activemq.apache.org/schema/core http://activemq.apache.org/schema/core/activemq-core.xsd">
|
||||
|
||||
<broker brokerName="sender" persistent="false" useJmx="true" xmlns="http://activemq.apache.org/schema/core">
|
||||
|
||||
<networkConnectors>
|
||||
<networkConnector uri="static:(tcp://localhost:62002)" userName="system" password="manager">
|
||||
<staticallyIncludedDestinations>
|
||||
<topic physicalName=">"/>
|
||||
</staticallyIncludedDestinations>
|
||||
</networkConnector>
|
||||
</networkConnectors>
|
||||
|
||||
<persistenceAdapter>
|
||||
<memoryPersistenceAdapter/>
|
||||
</persistenceAdapter>
|
||||
|
||||
<plugins>
|
||||
<simpleAuthenticationPlugin>
|
||||
<users>
|
||||
<authenticationUser username="system" password="manager"
|
||||
groups="users,admins"/>
|
||||
<authenticationUser username="user" password="user"
|
||||
groups="users"/>
|
||||
<authenticationUser username="guest" password="guest" groups="guests"/>
|
||||
</users>
|
||||
</simpleAuthenticationPlugin>
|
||||
|
||||
|
||||
<!-- lets configure a destination based authorization mechanism -->
|
||||
<authorizationPlugin>
|
||||
<map>
|
||||
<authorizationMap>
|
||||
<authorizationEntries>
|
||||
<authorizationEntry queue=">" read="admins" write="admins" admin="admins" />
|
||||
<authorizationEntry queue="USERS.>" read="users" write="users" admin="users" />
|
||||
<authorizationEntry queue="GUEST.>" read="guests" write="guests,users" admin="guests,users" />
|
||||
|
||||
<authorizationEntry queue="TEST.Q" read="guests" write="guests" />
|
||||
|
||||
<authorizationEntry topic=">" read="admins" write="admins" admin="admins" />
|
||||
<authorizationEntry topic="USERS.>" read="users" write="users" admin="users" />
|
||||
<authorizationEntry topic="GUEST.>" read="guests" write="guests,users" admin="guests,users" />
|
||||
|
||||
<authorizationEntry topic="ActiveMQ.Advisory.>" read="guests,users" write="guests,users" admin="guests,users"/>
|
||||
</authorizationEntries>
|
||||
<tempDestinationAuthorizationEntry>
|
||||
<tempDestinationAuthorizationEntry read="admins" write="admins" admin="admins"/>
|
||||
</tempDestinationAuthorizationEntry>
|
||||
</authorizationMap>
|
||||
</map>
|
||||
</authorizationPlugin>
|
||||
</plugins>
|
||||
|
||||
<transportConnectors>
|
||||
<transportConnector uri="tcp://localhost:62001"/>
|
||||
</transportConnectors>
|
||||
|
||||
</broker>
|
||||
|
||||
</beans>
|
Loading…
Reference in New Issue