You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by ro...@apache.org on 2010/05/31 18:03:44 UTC
svn commit: r949781 [2/5] - in /qpid/trunk/qpid/java: broker/etc/
broker/src/main/java/org/apache/qpid/qmf/
broker/src/main/java/org/apache/qpid/server/
broker/src/main/java/org/apache/qpid/server/binding/
broker/src/main/java/org/apache/qpid/server/co...
Modified: qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/management/MBeanInvocationHandlerImpl.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/management/MBeanInvocationHandlerImpl.java?rev=949781&r1=949780&r2=949781&view=diff
==============================================================================
--- qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/management/MBeanInvocationHandlerImpl.java (original)
+++ qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/management/MBeanInvocationHandlerImpl.java Mon May 31 16:03:41 2010
@@ -20,34 +20,36 @@
*/
package org.apache.qpid.server.management;
-import org.apache.qpid.management.common.mbeans.ConfigurationManagement;
-import org.apache.qpid.management.common.mbeans.LoggingManagement;
-import org.apache.qpid.management.common.mbeans.UserManagement;
-import org.apache.qpid.server.logging.actors.CurrentActor;
-import org.apache.qpid.server.logging.actors.ManagementActor;
-import org.apache.qpid.server.logging.messages.ManagementConsoleMessages;
-import org.apache.log4j.Logger;
-
-import javax.management.remote.MBeanServerForwarder;
-import javax.management.remote.JMXPrincipal;
-import javax.management.remote.JMXConnectionNotification;
-import javax.management.MBeanServer;
-import javax.management.ObjectName;
-import javax.management.MBeanInfo;
-import javax.management.MBeanOperationInfo;
-import javax.management.JMException;
-import javax.management.NotificationListener;
-import javax.management.Notification;
-import javax.security.auth.Subject;
import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.Proxy;
+import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.security.AccessControlContext;
import java.security.AccessController;
import java.security.Principal;
-import java.security.AccessControlContext;
-import java.util.HashSet;
-import java.util.Set;
import java.util.Properties;
+import java.util.Set;
+
+import javax.management.Attribute;
+import javax.management.JMException;
+import javax.management.MBeanInfo;
+import javax.management.MBeanOperationInfo;
+import javax.management.MBeanServer;
+import javax.management.Notification;
+import javax.management.NotificationListener;
+import javax.management.ObjectName;
+import javax.management.remote.JMXConnectionNotification;
+import javax.management.remote.JMXPrincipal;
+import javax.management.remote.MBeanServerForwarder;
+import javax.security.auth.Subject;
+
+import org.apache.log4j.Logger;
+import org.apache.qpid.server.logging.actors.CurrentActor;
+import org.apache.qpid.server.logging.actors.ManagementActor;
+import org.apache.qpid.server.logging.messages.ManagementConsoleMessages;
+import org.apache.qpid.server.registry.ApplicationRegistry;
+import org.apache.qpid.server.security.SecurityManager;
+import org.apache.qpid.server.security.access.Operation;
/**
* This class can be used by the JMXConnectorServer as an InvocationHandler for the mbean operations. This implements
@@ -65,18 +67,11 @@ public class MBeanInvocationHandlerImpl
private MBeanServer _mbs;
private static Properties _userRoles = new Properties();
private static ManagementActor _logActor;
-
- private static HashSet<String> _adminOnlyMethods = new HashSet<String>();
- {
- _adminOnlyMethods.add(UserManagement.TYPE);
- _adminOnlyMethods.add(LoggingManagement.TYPE);
- _adminOnlyMethods.add(ConfigurationManagement.TYPE);
- }
public static MBeanServerForwarder newProxyInstance()
{
final InvocationHandler handler = new MBeanInvocationHandlerImpl();
- final Class[] interfaces = new Class[]{MBeanServerForwarder.class};
+ final Class<?>[] interfaces = new Class[] { MBeanServerForwarder.class };
_logActor = new ManagementActor(CurrentActor.get().getRootMessageLogger());
@@ -87,7 +82,7 @@ public class MBeanInvocationHandlerImpl
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
{
- final String methodName = method.getName();
+ final String methodName = getMethodName(method, args);
if (methodName.equals("getMBeanServer"))
{
@@ -112,145 +107,165 @@ public class MBeanInvocationHandlerImpl
AccessControlContext acc = AccessController.getContext();
Subject subject = Subject.getSubject(acc);
- // Allow operations performed locally on behalf of the connector server itself
- if (subject == null)
- {
- return method.invoke(_mbs, args);
- }
-
- if (args == null || DELEGATE.equals(args[0]))
- {
- return method.invoke(_mbs, args);
- }
-
- // Restrict access to "createMBean" and "unregisterMBean" to any user
- if (methodName.equals("createMBean") || methodName.equals("unregisterMBean"))
- {
- _logger.debug("User trying to create or unregister an MBean");
- throw new SecurityException("Access denied");
- }
-
- // Retrieve JMXPrincipal from Subject
- Set<JMXPrincipal> principals = subject.getPrincipals(JMXPrincipal.class);
- if (principals == null || principals.isEmpty())
- {
- throw new SecurityException("Access denied");
- }
-
- Principal principal = principals.iterator().next();
- String identity = principal.getName();
-
- if (isAdminMethod(args))
+ try
{
- if (isAdmin(identity))
+ // Allow operations performed locally on behalf of the connector server itself
+ if (subject == null)
+ {
+ return method.invoke(_mbs, args);
+ }
+
+ if (args == null || DELEGATE.equals(args[0]))
{
return method.invoke(_mbs, args);
}
+
+ // Restrict access to "createMBean" and "unregisterMBean" to any user
+ if (methodName.equals("createMBean") || methodName.equals("unregisterMBean"))
+ {
+ _logger.debug("User trying to create or unregister an MBean");
+ throw new SecurityException("Access denied: " + methodName);
+ }
+
+ // Allow querying available object names
+ if (methodName.equals("queryNames"))
+ {
+ return method.invoke(_mbs, args);
+ }
+
+ // Retrieve JMXPrincipal from Subject
+ Set<JMXPrincipal> principals = subject.getPrincipals(JMXPrincipal.class);
+ if (principals == null || principals.isEmpty())
+ {
+ throw new SecurityException("Access denied: no principal");
+ }
+
+ // Save the principal
+ Principal principal = principals.iterator().next();
+ SecurityManager.setThreadPrincipal(principal);
+
+ // Get the component, type and impact, which may be null
+ String type = getType(method, args);
+ String vhost = getVirtualHost(method, args);
+ int impact = getImpact(method, args);
+
+ // Get the security manager for the virtual host (if set)
+ SecurityManager security;
+ if (vhost == null)
+ {
+ security = ApplicationRegistry.getInstance().getSecurityManager();
+ }
else
{
- throw new SecurityException("Access denied");
+ security = ApplicationRegistry.getInstance().getVirtualHostRegistry().getVirtualHost(vhost).getSecurityManager();
}
+
+ if (isAccessMethod(methodName) || impact == MBeanOperationInfo.INFO)
+ {
+ // Check for read-only method invocation permission
+ if (!security.authoriseMethod(Operation.ACCESS, type, methodName))
+ {
+ throw new SecurityException("Permission denied: Access " + methodName);
+ }
+ }
+ else if (isUpdateMethod(methodName))
+ {
+ // Check for setting properties permission
+ if (!security.authoriseMethod(Operation.UPDATE, type, methodName))
+ {
+ throw new SecurityException("Permission denied: Update " + methodName);
+ }
+ }
+ else
+ {
+ // Check for invoking/executing method action/operation permission
+ if (!security.authoriseMethod(Operation.EXECUTE, type, methodName))
+ {
+ throw new SecurityException("Permission denied: Execute " + methodName);
+ }
+ }
+
+ // Actually invoke the method
+ return method.invoke(_mbs, args);
}
-
- // Following users can perform any operation other than "createMBean" and "unregisterMBean"
- if (isAllowedToModify(identity))
- {
- return method.invoke(_mbs, args);
- }
-
- // These users can only call "getAttribute" on the MBeanServerDelegate MBean
- // Here we can add other fine grained permissions like specific method for a particular mbean
- if (isReadOnlyUser(identity) && isReadOnlyMethod(method, args))
+ catch (InvocationTargetException e)
{
- return method.invoke(_mbs, args);
+ throw e.getTargetException();
}
+ }
- throw new SecurityException("Access denied");
+ private String getType(Method method, Object[] args)
+ {
+ if (args[0] instanceof ObjectName)
+ {
+ ObjectName object = (ObjectName) args[0];
+ String type = object.getKeyProperty("type");
+
+ return type;
+ }
+ return null;
}
- private boolean isAdminMethod(Object[] args)
- {
+ private String getVirtualHost(Method method, Object[] args)
+ {
if (args[0] instanceof ObjectName)
{
ObjectName object = (ObjectName) args[0];
+ String vhost = object.getKeyProperty("VirtualHost");
- return _adminOnlyMethods.contains(object.getKeyProperty("type"));
- }
- return false;
- }
-
- // Initialises the user roles
- public static void setAccessRights(Properties accessRights)
- {
- _userRoles = accessRights;
- }
-
- private boolean isAdmin(String userName)
- {
- if (ADMIN.equals(_userRoles.getProperty(userName)))
- {
- return true;
+ return vhost;
}
- return false;
+ return null;
}
-
- private boolean isAllowedToModify(String userName)
+
+ private String getMethodName(Method method, Object[] args)
{
- if (ADMIN.equals(_userRoles.getProperty(userName))
- || READWRITE.equals(_userRoles.getProperty(userName)))
- {
- return true;
- }
- return false;
- }
+ String methodName = method.getName();
- private boolean isReadOnlyUser(String userName)
- {
- if (READONLY.equals(_userRoles.getProperty(userName)))
+ // if arguments are set, try and work out real method name
+ if (args != null && args.length >= 1 && args[0] instanceof ObjectName)
{
- return true;
+ if (methodName.equals("getAttribute"))
+ {
+ methodName = "get" + (String) args[1];
+ }
+ else if (methodName.equals("setAttribute"))
+ {
+ methodName = "set" + ((Attribute) args[1]).getName();
+ }
+ else if (methodName.equals("invoke"))
+ {
+ methodName = (String) args[1];
+ }
}
- return false;
+
+ return methodName;
}
- private boolean isReadOnlyMethod(Method method, Object[] args)
+ private int getImpact(Method method, Object[] args)
{
- String methodName = method.getName();
-
- //handle standard get/set/query and select 'is' methods from MBeanServer
- if (methodName.startsWith("query") || methodName.startsWith("get")
- ||methodName.startsWith("isInstanceOf") || methodName.startsWith("isRegistered"))
- {
- return true;
- }
- else if (methodName.startsWith("set"))
- {
- return false;
- }
-
//handle invocation of other methods on mbeans
- if ((args[0] instanceof ObjectName) && (methodName.equals("invoke")))
+ if ((args[0] instanceof ObjectName) && (method.getName().equals("invoke")))
{
-
//get invoked method name
String mbeanMethod = (args.length > 1) ? (String) args[1] : null;
if (mbeanMethod == null)
{
- return false;
+ return -1;
}
-
+
try
{
- //check if the given method is tagged with an INFO impact attribute
+ //Get the impact attribute
MBeanInfo mbeanInfo = _mbs.getMBeanInfo((ObjectName) args[0]);
if (mbeanInfo != null)
{
MBeanOperationInfo[] opInfos = mbeanInfo.getOperations();
for (MBeanOperationInfo opInfo : opInfos)
{
- if (opInfo.getName().equals(mbeanMethod) && (opInfo.getImpact() == MBeanOperationInfo.INFO))
+ if (opInfo.getName().equals(mbeanMethod))
{
- return true;
+ return opInfo.getImpact();
}
}
}
@@ -261,7 +276,20 @@ public class MBeanInvocationHandlerImpl
}
}
- return false;
+ return -1;
+ }
+
+ private boolean isAccessMethod(String methodName)
+ {
+ //handle standard get/query/is methods from MBeanServer
+ return (methodName.startsWith("query") || methodName.startsWith("get") || methodName.startsWith("is"));
+ }
+
+
+ private boolean isUpdateMethod(String methodName)
+ {
+ //handle standard set methods from MBeanServer
+ return methodName.startsWith("set");
}
public void handleNotification(Notification notification, Object handback)
Modified: qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolEngine.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolEngine.java?rev=949781&r1=949780&r2=949781&view=diff
==============================================================================
--- qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolEngine.java (original)
+++ qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolEngine.java Mon May 31 16:03:41 2010
@@ -20,16 +20,52 @@
*/
package org.apache.qpid.server.protocol;
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.net.SocketAddress;
+import java.nio.ByteBuffer;
+import java.security.Principal;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+import java.util.Map.Entry;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.CopyOnWriteArraySet;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicLong;
+
+import javax.management.JMException;
+import javax.security.sasl.SaslServer;
+
import org.apache.log4j.Logger;
import org.apache.mina.transport.vmpipe.VmPipeAddress;
-
import org.apache.qpid.AMQChannelException;
import org.apache.qpid.AMQConnectionException;
import org.apache.qpid.AMQException;
+import org.apache.qpid.AMQSecurityException;
import org.apache.qpid.codec.AMQCodecFactory;
import org.apache.qpid.codec.AMQDecoder;
import org.apache.qpid.common.ClientProperties;
-import org.apache.qpid.framing.*;
+import org.apache.qpid.framing.AMQBody;
+import org.apache.qpid.framing.AMQDataBlock;
+import org.apache.qpid.framing.AMQFrame;
+import org.apache.qpid.framing.AMQMethodBody;
+import org.apache.qpid.framing.AMQProtocolHeaderException;
+import org.apache.qpid.framing.AMQShortString;
+import org.apache.qpid.framing.ChannelCloseBody;
+import org.apache.qpid.framing.ChannelCloseOkBody;
+import org.apache.qpid.framing.ConnectionCloseBody;
+import org.apache.qpid.framing.ContentBody;
+import org.apache.qpid.framing.ContentHeaderBody;
+import org.apache.qpid.framing.FieldTable;
+import org.apache.qpid.framing.HeartbeatBody;
+import org.apache.qpid.framing.MethodDispatcher;
+import org.apache.qpid.framing.MethodRegistry;
+import org.apache.qpid.framing.ProtocolInitiation;
+import org.apache.qpid.framing.ProtocolVersion;
import org.apache.qpid.pool.Job;
import org.apache.qpid.pool.ReferenceCountingExecutorService;
import org.apache.qpid.protocol.AMQConstant;
@@ -61,25 +97,6 @@ import org.apache.qpid.server.virtualhos
import org.apache.qpid.transport.NetworkDriver;
import org.apache.qpid.transport.Sender;
-import javax.management.JMException;
-import javax.security.sasl.SaslServer;
-import java.io.IOException;
-import java.net.InetSocketAddress;
-import java.net.SocketAddress;
-import java.nio.ByteBuffer;
-import java.security.Principal;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.UUID;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.CopyOnWriteArrayList;
-import java.util.concurrent.CopyOnWriteArraySet;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.atomic.AtomicLong;
-
public class AMQProtocolEngine implements ProtocolEngine, Managable, AMQProtocolSession, ConnectionConfig
{
private static final Logger _logger = Logger.getLogger(AMQProtocolEngine.class);
@@ -117,6 +134,7 @@ public class AMQProtocolEngine implement
private Object _lastSent;
protected volatile boolean _closed;
+
// maximum number of channels this session should have
private long _maxNoOfChannels = 1000;
@@ -358,14 +376,12 @@ public class AMQProtocolEngine implement
public void methodFrameReceived(int channelId, AMQMethodBody methodBody)
{
-
final AMQMethodEvent<AMQMethodBody> evt = new AMQMethodEvent<AMQMethodBody>(channelId, methodBody);
try
{
try
{
-
boolean wasAnyoneInterested = _stateManager.methodReceived(evt);
if (!_frameListeners.isEmpty())
@@ -418,10 +434,15 @@ public class AMQProtocolEngine implement
_logger.info(e.getMessage() + " whilst processing:" + methodBody);
closeConnection(channelId, e, false);
}
+ catch (AMQSecurityException e)
+ {
+ AMQConnectionException ce = evt.getMethod().getConnectionException(AMQConstant.ACCESS_REFUSED, e.getMessage());
+ _logger.info(e.getMessage() + " whilst processing:" + methodBody);
+ closeConnection(channelId, ce, false);
+ }
}
catch (Exception e)
{
-
for (AMQMethodListener listener : _frameListeners)
{
listener.error(e);
@@ -999,7 +1020,6 @@ public class AMQProtocolEngine implement
{
if (throwable instanceof AMQProtocolHeaderException)
{
-
writeFrame(new ProtocolInitiation(ProtocolVersion.getLatestSupportedVersion()));
_networkDriver.close();
Modified: qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueue.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueue.java?rev=949781&r1=949780&r2=949781&view=diff
==============================================================================
--- qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueue.java (original)
+++ qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueue.java Mon May 31 16:03:41 2010
@@ -21,6 +21,7 @@
package org.apache.qpid.server.queue;
import org.apache.qpid.AMQException;
+import org.apache.qpid.AMQSecurityException;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.server.AMQChannel;
import org.apache.qpid.server.protocol.AMQConnectionModel;
@@ -194,7 +195,7 @@ public interface AMQQueue extends Managa
void deleteMessageFromTop();
- long clearQueue();
+ long clearQueue() throws AMQException;
/**
* Checks the status of messages on the queue, purging expired ones, firing age related alerts etc.
Modified: qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueFactory.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueFactory.java?rev=949781&r1=949780&r2=949781&view=diff
==============================================================================
--- qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueFactory.java (original)
+++ qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueFactory.java Mon May 31 16:03:41 2010
@@ -21,6 +21,7 @@
package org.apache.qpid.server.queue;
import org.apache.qpid.AMQException;
+import org.apache.qpid.AMQSecurityException;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.framing.FieldTable;
import org.apache.qpid.server.virtualhost.VirtualHost;
@@ -29,7 +30,6 @@ import org.apache.qpid.server.configurat
import java.util.Map;
import java.util.HashMap;
-
public class AMQQueueFactory
{
public static final AMQShortString X_QPID_PRIORITIES = new AMQShortString("x-qpid-priorities");
@@ -128,22 +128,20 @@ public class AMQQueueFactory
};
-
+ /** @see #createAMQQueueImpl(String, boolean, String, boolean, boolean, VirtualHost, Map) */
public static AMQQueue createAMQQueueImpl(AMQShortString name,
boolean durable,
AMQShortString owner,
boolean autoDelete,
- boolean exclusive,
- VirtualHost virtualHost,
- final FieldTable arguments)
+ boolean exclusive,
+ VirtualHost virtualHost, final FieldTable arguments) throws AMQException
{
return createAMQQueueImpl(name == null ? null : name.toString(),
durable,
owner == null ? null : owner.toString(),
autoDelete,
exclusive,
- virtualHost,
- FieldTable.convertToMap(arguments));
+ virtualHost, FieldTable.convertToMap(arguments));
}
@@ -152,8 +150,15 @@ public class AMQQueueFactory
String owner,
boolean autoDelete,
boolean exclusive,
- VirtualHost virtualHost, Map<String, Object> arguments)
+ VirtualHost virtualHost, Map<String, Object> arguments) throws AMQSecurityException
{
+ // Access check
+ if (!virtualHost.getSecurityManager().authoriseCreateQueue(autoDelete, durable, exclusive, null, null, new AMQShortString(queueName), owner))
+ {
+ String description = "Permission denied: queue-name '" + queueName + "'";
+ throw new AMQSecurityException(description);
+ }
+
int priorities = 1;
String conflationKey = null;
if(arguments != null)
Modified: qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueMBean.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueMBean.java?rev=949781&r1=949780&r2=949781&view=diff
==============================================================================
--- qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueMBean.java (original)
+++ qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueMBean.java Mon May 31 16:03:41 2010
@@ -28,6 +28,7 @@ import org.apache.qpid.framing.ContentHe
import org.apache.qpid.management.common.mbeans.ManagedQueue;
import org.apache.qpid.management.common.mbeans.annotations.MBeanConstructor;
import org.apache.qpid.management.common.mbeans.annotations.MBeanDescription;
+import org.apache.qpid.server.logging.actors.CurrentActor;
import org.apache.qpid.server.management.AMQManagedObject;
import org.apache.qpid.server.management.ManagedObject;
import org.apache.qpid.server.message.ServerMessage;
@@ -39,6 +40,7 @@ import org.apache.qpid.server.txn.LocalT
import org.apache.qpid.transport.MessageProperties;
import javax.management.JMException;
+import javax.management.MBeanException;
import javax.management.MBeanNotificationInfo;
import javax.management.Notification;
import javax.management.OperationsException;
@@ -336,7 +338,14 @@ public class AMQQueueMBean extends AMQMa
*/
public Long clearQueue() throws JMException
{
- return _queue.clearQueue();
+ try
+ {
+ return _queue.clearQueue();
+ }
+ catch (AMQException ex)
+ {
+ throw new MBeanException(ex, "Error clearing queue " + _queueName);
+ }
}
/**
Modified: qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/SimpleAMQQueue.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/SimpleAMQQueue.java?rev=949781&r1=949780&r2=949781&view=diff
==============================================================================
--- qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/SimpleAMQQueue.java (original)
+++ qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/SimpleAMQQueue.java Mon May 31 16:03:41 2010
@@ -1,11 +1,31 @@
+/*
+ * 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.qpid.server.queue;
import org.apache.log4j.Logger;
import org.apache.qpid.AMQException;
+import org.apache.qpid.AMQSecurityException;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.pool.ReadWriteRunnable;
import org.apache.qpid.pool.ReferenceCountingExecutorService;
+import org.apache.qpid.protocol.AMQConstant;
import org.apache.qpid.server.AMQChannel;
import org.apache.qpid.server.protocol.AMQConnectionModel;
import org.apache.qpid.server.protocol.AMQSessionModel;
@@ -50,26 +70,6 @@ import java.util.concurrent.atomic.Atomi
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicReference;
-/*
-*
-* 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.
-*
-*/
public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener
{
private static final Logger _logger = Logger.getLogger(SimpleAMQQueue.class);
@@ -386,9 +386,16 @@ public class SimpleAMQQueue implements A
// ------ Manage Subscriptions
- public synchronized void registerSubscription(final Subscription subscription, final boolean exclusive) throws AMQException
+ public synchronized void registerSubscription(final Subscription subscription, final boolean exclusive)
+ throws AMQSecurityException, ExistingExclusiveSubscription, ExistingSubscriptionPreventsExclusive
{
-
+ // Access control
+ if (!getVirtualHost().getSecurityManager().authoriseConsume(this))
+ {
+ throw new AMQSecurityException("Permission denied");
+ }
+
+
if (hasExclusiveSubscriber())
{
throw new ExistingExclusiveSubscription();
@@ -403,7 +410,6 @@ public class SimpleAMQQueue implements A
else
{
_exclusiveSubscriber = subscription;
-
}
}
@@ -1212,38 +1218,9 @@ public class SimpleAMQQueue implements A
}
- public void purge(final long request)
+ public void purge(final long request) throws AMQException
{
- if(request == 0l)
- {
- clearQueue();
- }
- else if(request > 0l)
- {
-
- QueueEntryIterator queueListIterator = _entries.iterator();
- long count = 0;
-
- ServerTransaction txn = new LocalTransaction(getVirtualHost().getTransactionLog());
-
- while (queueListIterator.advance())
- {
- QueueEntry node = queueListIterator.getNode();
- if (!node.isDeleted() && node.acquire())
- {
- dequeueEntry(node, txn);
- if(++count == request)
- {
- break;
- }
- }
-
- }
-
- txn.commit();
-
-
- }
+ clear(request);
}
public long getCreateTime()
@@ -1270,9 +1247,19 @@ public class SimpleAMQQueue implements A
}
}
- public long clearQueue()
- {
+ public long clearQueue() throws AMQException
+ {
+ return clear(0l);
+ }
+ private long clear(final long request) throws AMQSecurityException
+ {
+ //Perform ACLs
+ if (!getVirtualHost().getSecurityManager().authorisePurge(this))
+ {
+ throw new AMQSecurityException("Permission denied: queue " + getName());
+ }
+
QueueEntryIterator queueListIterator = _entries.iterator();
long count = 0;
@@ -1284,7 +1271,10 @@ public class SimpleAMQQueue implements A
if (!node.isDeleted() && node.acquire())
{
dequeueEntry(node, txn);
- count++;
+ if(++count == request)
+ {
+ break;
+ }
}
}
@@ -1292,7 +1282,6 @@ public class SimpleAMQQueue implements A
txn.commit();
return count;
-
}
private void dequeueEntry(final QueueEntry node)
@@ -1329,12 +1318,18 @@ public class SimpleAMQQueue implements A
_deleteTaskList.remove(task);
}
- public int delete() throws AMQException
+ // TODO list all thrown exceptions
+ public int delete() throws AMQSecurityException, AMQException
{
if (!_deleted.getAndSet(true))
{
+ // Check access
+ if (!_virtualHost.getSecurityManager().authoriseDelete(this))
+ {
+ throw new AMQSecurityException("Permission denied: " + getName());
+ }
- for(Binding b : getBindings())
+ for (Binding b : getBindings())
{
_virtualHost.getBindingFactory().removeBinding(b);
}
@@ -1606,6 +1601,11 @@ public class SimpleAMQQueue implements A
public void flushSubscription(Subscription sub) throws AMQException
{
+ // Access control
+ if (!getVirtualHost().getSecurityManager().authoriseConsume(this))
+ {
+ throw new AMQSecurityException("Permission denied: " + getName());
+ }
flushSubscription(sub, Long.MAX_VALUE);
}
Modified: qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/registry/ApplicationRegistry.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/registry/ApplicationRegistry.java?rev=949781&r1=949780&r2=949781&view=diff
==============================================================================
--- qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/registry/ApplicationRegistry.java (original)
+++ qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/registry/ApplicationRegistry.java Mon May 31 16:03:41 2010
@@ -124,7 +124,6 @@ public abstract class ApplicationRegistr
@SuppressWarnings("finally")
public static void initialise(IApplicationRegistry instance, int instanceID) throws Exception
{
- _logger.error("initialise(IApplicationRegistry instance, int instanceID)");
if (instance != null)
{
_logger.info("Initialising Application Registry(" + instance + "):" + instanceID);
@@ -142,7 +141,6 @@ public abstract class ApplicationRegistr
try
{
- _logger.error("instance.initialise(instanceID)");
instance.initialise(instanceID);
}
catch (Exception e)
@@ -237,12 +235,11 @@ public abstract class ApplicationRegistr
public void configure() throws ConfigurationException
{
-
_configurationManager = new ConfigurationManager();
try
{
- _pluginManager = new PluginManager(_configuration.getPluginDirectory());
+ _pluginManager = new PluginManager(_configuration.getPluginDirectory(), _configuration.getCacheDirectory());
}
catch (Exception e)
{
Added: qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/AbstractPlugin.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/AbstractPlugin.java?rev=949781&view=auto
==============================================================================
--- qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/AbstractPlugin.java (added)
+++ qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/AbstractPlugin.java Mon May 31 16:03:41 2010
@@ -0,0 +1,69 @@
+/*
+ *
+ * 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.qpid.server.security;
+
+import org.apache.log4j.Logger;
+import org.apache.qpid.server.configuration.plugins.ConfigurationPlugin;
+import org.apache.qpid.server.security.access.ObjectProperties;
+import org.apache.qpid.server.security.access.ObjectType;
+import org.apache.qpid.server.security.access.Operation;
+
+/**
+ * This is intended as the parent for all simple plugins.
+ */
+public abstract class AbstractPlugin implements SecurityPlugin
+{
+ protected final Logger _logger = Logger.getLogger(getClass());
+
+ public ConfigurationPlugin _config;
+
+ public String getPluginName()
+ {
+ return getClass().getSimpleName();
+ }
+
+ public Result getDefault()
+ {
+ return Result.ABSTAIN;
+ }
+
+ public abstract Result access(ObjectType object, Object instance);
+
+ public abstract Result authorise(Operation operation, ObjectType object, ObjectProperties properties);
+
+ public boolean isConfigured()
+ {
+ if (_config == null)
+ {
+ return false;
+ }
+
+ for (String key : _config.getElementsProcessed())
+ {
+ if (!_config.getConfig().containsKey(key) && _config.getConfig().subset(key).isEmpty())
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+}
Added: qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/AbstractProxyPlugin.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/AbstractProxyPlugin.java?rev=949781&view=auto
==============================================================================
--- qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/AbstractProxyPlugin.java (added)
+++ qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/AbstractProxyPlugin.java Mon May 31 16:03:41 2010
@@ -0,0 +1,139 @@
+/*
+ *
+ * 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.qpid.server.security;
+
+import org.apache.commons.configuration.Configuration;
+import org.apache.qpid.server.security.access.ObjectProperties;
+import org.apache.qpid.server.security.access.ObjectType;
+import org.apache.qpid.server.security.access.Operation;
+
+/**
+ * This {@link SecurityPlugin} proxies the authorise calls to a serries of methods, one per {@link Operation}.
+ *
+ * Plugins that extend this class should override the relevant authorise method and implement their own
+ * {@link #setConfiguration(Configuration)} method.
+ */
+public abstract class AbstractProxyPlugin extends AbstractPlugin
+{
+ public Result authoriseConsume(ObjectType object, ObjectProperties properties)
+ {
+ return getDefault();
+ }
+
+ public Result authorisePublish(ObjectType object, ObjectProperties properties)
+ {
+ return getDefault();
+ }
+
+ public Result authoriseCreate(ObjectType object, ObjectProperties properties)
+ {
+ return getDefault();
+ }
+
+ public Result authoriseAccess(ObjectType object, ObjectProperties properties)
+ {
+ return getDefault();
+ }
+
+ public Result authoriseBind(ObjectType object, ObjectProperties properties)
+ {
+ return getDefault();
+ }
+
+ public Result authoriseUnbind(ObjectType object, ObjectProperties properties)
+ {
+ return getDefault();
+ }
+
+ public Result authoriseDelete(ObjectType object, ObjectProperties properties)
+ {
+ return getDefault();
+ }
+
+ public Result authorisePurge(ObjectType object, ObjectProperties properties)
+ {
+ return getDefault();
+ }
+
+ public Result authoriseExecute(ObjectType object, ObjectProperties properties)
+ {
+ return getDefault();
+ }
+
+ public Result authoriseUpdate(ObjectType object, ObjectProperties properties)
+ {
+ return getDefault();
+ }
+
+ public Result accessBroker(Object instance)
+ {
+ return getDefault();
+ }
+
+ public Result accessVirtualhost(Object instance)
+ {
+ return getDefault();
+ }
+
+ @Override
+ public Result access(ObjectType objectType, Object instance)
+ {
+ switch (objectType)
+ {
+ case BROKER:
+ return accessBroker(instance);
+ case VIRTUALHOST:
+ return accessVirtualhost(instance);
+ }
+
+ return getDefault();
+ }
+
+ @Override
+ public Result authorise(Operation operation, ObjectType objectType, ObjectProperties properties)
+ {
+ switch (operation)
+ {
+ case CONSUME:
+ return authoriseConsume(objectType, properties);
+ case PUBLISH:
+ return authorisePublish(objectType, properties);
+ case CREATE:
+ return authoriseCreate(objectType, properties);
+ case ACCESS:
+ return authoriseAccess(objectType, properties);
+ case BIND:
+ return authoriseBind(objectType, properties);
+ case UNBIND:
+ return authoriseUnbind(objectType, properties);
+ case DELETE:
+ return authoriseDelete(objectType, properties);
+ case PURGE:
+ return authorisePurge(objectType, properties);
+ case EXECUTE:
+ return authoriseExecute(objectType, properties);
+ case UPDATE:
+ return authoriseUpdate(objectType, properties);
+ }
+
+ return getDefault();
+ }
+}
Copied: qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/Result.java (from r949780, qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/Permission.java)
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/Result.java?p2=qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/Result.java&p1=qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/Permission.java&r1=949780&r2=949781&rev=949781&view=diff
==============================================================================
--- qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/Permission.java (original)
+++ qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/Result.java Mon May 31 16:03:41 2010
@@ -15,24 +15,32 @@
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
- *
- *
*/
-package org.apache.qpid.server.security.access;
+package org.apache.qpid.server.security;
-import org.apache.qpid.framing.AMQShortString;
-import org.apache.qpid.server.exchange.Exchange;
-import org.apache.qpid.server.queue.AMQQueue;
-
-public enum Permission
+/**
+ * The result of a security plugin decision, normally {@link #ALLOWED} or {@link #DENIED}.
+ */
+public enum Result
{
- CONSUME,
- PUBLISH,
- CREATEQUEUE,
- CREATEEXCHANGE,
- ACCESS,
- BIND,
- UNBIND,
- DELETE,
- PURGE
-}
+ /**
+ * The request is allowed.
+ */
+ ALLOWED,
+
+ /**
+ * The request is denied.
+ */
+ DENIED,
+
+ /**
+ * Indicates that a plugin does not handle a particular type of request.
+ */
+ ABSTAIN,
+
+ /**
+ * A plugin instance cannot make a decision on a request it is able to handle,
+ * and another instance of the plugin should be checked.
+ */
+ DEFER;
+}
\ No newline at end of file
Added: qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/SecurityManager.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/SecurityManager.java?rev=949781&view=auto
==============================================================================
--- qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/SecurityManager.java (added)
+++ qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/SecurityManager.java Mon May 31 16:03:41 2010
@@ -0,0 +1,384 @@
+/*
+ * 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.qpid.server.security;
+
+import static org.apache.qpid.server.security.access.ObjectType.*;
+import static org.apache.qpid.server.security.access.Operation.*;
+
+import java.security.Principal;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.apache.commons.configuration.ConfigurationException;
+import org.apache.log4j.Logger;
+import org.apache.qpid.framing.AMQShortString;
+import org.apache.qpid.server.configuration.plugins.ConfigurationPlugin;
+import org.apache.qpid.server.exchange.Exchange;
+import org.apache.qpid.server.plugins.PluginManager;
+import org.apache.qpid.server.protocol.AMQProtocolSession;
+import org.apache.qpid.server.queue.AMQQueue;
+import org.apache.qpid.server.security.access.ObjectProperties;
+import org.apache.qpid.server.security.access.Operation;
+import org.apache.qpid.server.security.auth.sasl.UsernamePrincipal;
+
+/**
+ * The security manager contains references to all loaded {@link SecurityPlugin}s and delegates security decisions to them based
+ * on virtual host name. The plugins can be external <em>OSGi</em> .jar files that export the required classes or just internal
+ * objects for simpler plugins.
+ *
+ * @see SecurityPlugin
+ */
+public class SecurityManager
+{
+ private static final Logger _logger = Logger.getLogger(SecurityManager.class);
+
+ /** Container for the {@link Principal} that is using to this thread. */
+ private static final ThreadLocal<Principal> _principal = new ThreadLocal<Principal>();
+
+ private PluginManager _pluginManager;
+ private Map<String, SecurityPluginFactory> _pluginFactories = new HashMap<String, SecurityPluginFactory>();
+ private Map<String, SecurityPlugin> _globalPlugins = new HashMap<String, SecurityPlugin>();
+ private Map<String, SecurityPlugin> _hostPlugins = new HashMap<String, SecurityPlugin>();
+
+ public SecurityManager(SecurityManager parent) throws ConfigurationException
+ {
+ _pluginManager = parent._pluginManager;
+ _pluginFactories = parent._pluginFactories;
+
+ // our global plugins are the parent's host plugins
+ _globalPlugins = parent._hostPlugins;
+ }
+
+ public SecurityManager(ConfigurationPlugin configuration, PluginManager manager) throws ConfigurationException
+ {
+ this(configuration, manager, null);
+ }
+
+ public SecurityManager(ConfigurationPlugin configuration, PluginManager manager, SecurityPluginFactory plugin) throws ConfigurationException
+ {
+ _pluginManager = manager;
+ if (manager == null) // No plugin manager, no plugins
+ {
+ return;
+ }
+
+ _pluginFactories = _pluginManager.getSecurityPlugins();
+ if (plugin != null)
+ {
+ _pluginFactories.put(plugin.getPluginName(), plugin);
+ }
+
+ configureHostPlugins(configuration);
+ }
+
+ public static Principal getThreadPrincipal()
+ {
+ return _principal.get();
+ }
+
+ public static void setThreadPrincipal(Principal principal)
+ {
+ _principal.set(principal);
+ }
+
+ public static void setThreadPrincipal(String authId)
+ {
+ setThreadPrincipal(new UsernamePrincipal(authId));
+ }
+
+ public void configureHostPlugins(ConfigurationPlugin hostConfig) throws ConfigurationException
+ {
+ _hostPlugins = configurePlugins(hostConfig);
+ }
+
+ public void configureGlobalPlugins(ConfigurationPlugin configuration) throws ConfigurationException
+ {
+ _globalPlugins = configurePlugins(configuration);
+ }
+
+ public Map<String, SecurityPlugin> configurePlugins(ConfigurationPlugin hostConfig) throws ConfigurationException
+ {
+ Map<String, SecurityPlugin> plugins = new HashMap<String, SecurityPlugin>();
+ for (SecurityPluginFactory<?> factory : _pluginFactories.values())
+ {
+ SecurityPlugin plugin = factory.newInstance(hostConfig);
+ if (plugin.isConfigured())
+ {
+ plugins.put(factory.getPluginName(), plugin);
+ }
+ }
+ return plugins;
+ }
+
+ public void addHostPlugin(SecurityPlugin plugin)
+ {
+ _hostPlugins.put(plugin.getClass().getName(), plugin);
+ }
+
+ public static Logger getLogger()
+ {
+ return _logger;
+ }
+
+ private abstract class AccessCheck
+ {
+ abstract Result allowed(SecurityPlugin plugin);
+ }
+
+ private boolean checkAllPlugins(AccessCheck checker)
+ {
+ HashMap<String, SecurityPlugin> remainingPlugins = new HashMap<String, SecurityPlugin>(_globalPlugins);
+
+ for (Entry<String, SecurityPlugin> hostEntry : _hostPlugins.entrySet())
+ {
+ // Create set of global only plugins
+ SecurityPlugin globalPlugin = remainingPlugins.get(hostEntry.getKey());
+ if (globalPlugin != null)
+ {
+ remainingPlugins.remove(hostEntry.getKey());
+ }
+
+ Result host = checker.allowed(hostEntry.getValue());
+
+ if (host == Result.DENIED)
+ {
+ // Something vetoed the access, we're done
+ return false;
+ }
+
+ // host allow overrides global allow, so only check global on abstain or defer
+ if (host != Result.ALLOWED)
+ {
+ if (globalPlugin == null)
+ {
+ if (host == Result.DEFER)
+ {
+ host = hostEntry.getValue().getDefault();
+ }
+ if (host == Result.DENIED)
+ {
+ return false;
+ }
+ }
+ else
+ {
+ Result global = checker.allowed(globalPlugin);
+ if (global == Result.DEFER)
+ {
+ global = globalPlugin.getDefault();
+ }
+ if (global == Result.ABSTAIN && host == Result.DEFER)
+ {
+ global = hostEntry.getValue().getDefault();
+ }
+ if (global == Result.DENIED)
+ {
+ return false;
+ }
+ }
+ }
+ }
+
+ for (SecurityPlugin plugin : remainingPlugins.values())
+ {
+ Result remaining = checker.allowed(plugin);
+ if (remaining == Result.DEFER)
+ {
+ remaining = plugin.getDefault();
+ }
+ if (remaining == Result.DENIED)
+ {
+ return false;
+ }
+ }
+
+ // getting here means either allowed or abstained from all plugins
+ return true;
+ }
+
+ public boolean authoriseBind(final Exchange exch, final AMQQueue queue, final AMQShortString routingKey)
+ {
+ return checkAllPlugins(new AccessCheck()
+ {
+ Result allowed(SecurityPlugin plugin)
+ {
+ return plugin.authorise(BIND, EXCHANGE, new ObjectProperties(exch, queue, routingKey));
+ }
+ });
+ }
+
+ // TODO not implemented yet, awaiting consensus
+ public boolean authoriseObject(final String packageName, final String className)
+ {
+ return checkAllPlugins(new AccessCheck()
+ {
+ Result allowed(SecurityPlugin plugin)
+ {
+ ObjectProperties properties = new ObjectProperties();
+ properties.put(ObjectProperties.Property.PACKAGE, packageName);
+ properties.put(ObjectProperties.Property.CLASS, className);
+ return plugin.authorise(ACCESS, OBJECT, properties);
+ }
+ });
+ }
+
+ public boolean authoriseMethod(final Operation operation, final String componentName, final String methodName)
+ {
+ return checkAllPlugins(new AccessCheck()
+ {
+ Result allowed(SecurityPlugin plugin)
+ {
+ ObjectProperties properties = new ObjectProperties();
+ properties.setName(methodName);
+ if (componentName != null)
+ {
+ // Only set the property if there is a component name
+ properties.put(ObjectProperties.Property.COMPONENT, componentName);
+ }
+ return plugin.authorise(operation, METHOD, properties);
+ }
+ });
+ }
+
+ // TODO not implemented yet, awaiting consensus
+ public boolean accessBroker(final AMQProtocolSession session)
+ {
+ return checkAllPlugins(new AccessCheck()
+ {
+ Result allowed(SecurityPlugin plugin)
+ {
+ return plugin.access(BROKER, session);
+ }
+ });
+ }
+
+ public boolean accessVirtualhost(final String vhostname, final String remoteAddress)
+ {
+ return checkAllPlugins(new AccessCheck()
+ {
+ Result allowed(SecurityPlugin plugin)
+ {
+ return plugin.access(VIRTUALHOST, remoteAddress);
+ }
+ });
+ }
+
+ public boolean authoriseConsume(final AMQQueue queue)
+ {
+ return checkAllPlugins(new AccessCheck()
+ {
+ Result allowed(SecurityPlugin plugin)
+ {
+ return plugin.authorise(CONSUME, QUEUE, new ObjectProperties(queue));
+ }
+ });
+ }
+
+ public boolean authoriseConsume(final boolean exclusive, final boolean noAck, final boolean noLocal, final boolean nowait, final AMQQueue queue)
+ {
+ return checkAllPlugins(new AccessCheck()
+ {
+ Result allowed(SecurityPlugin plugin)
+ {
+ return plugin.authorise(CONSUME, QUEUE, new ObjectProperties(exclusive, noAck, noLocal, nowait, queue));
+ }
+ });
+ }
+
+ public boolean authoriseCreateExchange(final Boolean autoDelete, final Boolean durable, final AMQShortString exchangeName,
+ final Boolean internal, final Boolean nowait, final Boolean passive, final AMQShortString exchangeType)
+ {
+ return checkAllPlugins(new AccessCheck()
+ {
+ Result allowed(SecurityPlugin plugin)
+ {
+ return plugin.authorise(CREATE, EXCHANGE, new ObjectProperties(autoDelete, durable, exchangeName,
+ internal, nowait, passive, exchangeType));
+ }
+ });
+ }
+
+ public boolean authoriseCreateQueue(final Boolean autoDelete, final Boolean durable, final Boolean exclusive,
+ final Boolean nowait, final Boolean passive, final AMQShortString queueName, final String owner)
+ {
+ return checkAllPlugins(new AccessCheck()
+ {
+ Result allowed(SecurityPlugin plugin)
+ {
+ return plugin.authorise(CREATE, QUEUE, new ObjectProperties(autoDelete, durable, exclusive, nowait, passive, queueName, owner));
+ }
+ });
+ }
+
+ public boolean authoriseDelete(final AMQQueue queue)
+ {
+ return checkAllPlugins(new AccessCheck()
+ {
+ Result allowed(SecurityPlugin plugin)
+ {
+ return plugin.authorise(DELETE, QUEUE, new ObjectProperties(queue));
+ }
+ });
+ }
+
+ public boolean authoriseDelete(final Exchange exchange)
+ {
+ return checkAllPlugins(new AccessCheck()
+ {
+ Result allowed(SecurityPlugin plugin)
+ {
+ return plugin.authorise(DELETE, EXCHANGE, new ObjectProperties(exchange.getName()));
+ }
+ });
+ }
+
+ public boolean authorisePublish(final boolean immediate, final String routingKey, final String exchangeName)
+ {
+ return checkAllPlugins(new AccessCheck()
+ {
+ Result allowed(SecurityPlugin plugin)
+ {
+ return plugin.authorise(PUBLISH, EXCHANGE, new ObjectProperties(exchangeName, routingKey, immediate));
+ }
+ });
+ }
+
+ public boolean authorisePurge(final AMQQueue queue)
+ {
+ return checkAllPlugins(new AccessCheck()
+ {
+ Result allowed(SecurityPlugin plugin)
+ {
+ return plugin.authorise(PURGE, QUEUE, new ObjectProperties(queue));
+ }
+ });
+ }
+
+ public boolean authoriseUnbind(final Exchange exch, final AMQShortString routingKey, final AMQQueue queue)
+ {
+ return checkAllPlugins(new AccessCheck()
+ {
+ Result allowed(SecurityPlugin plugin)
+ {
+ return plugin.authorise(UNBIND, EXCHANGE, new ObjectProperties(exch, queue, routingKey));
+ }
+ });
+ }
+}
Propchange: qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/SecurityManager.java
------------------------------------------------------------------------------
svn:executable = *
Added: qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/SecurityPlugin.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/SecurityPlugin.java?rev=949781&view=auto
==============================================================================
--- qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/SecurityPlugin.java (added)
+++ qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/SecurityPlugin.java Mon May 31 16:03:41 2010
@@ -0,0 +1,47 @@
+/*
+ * 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.qpid.server.security;
+
+import org.apache.qpid.server.plugins.Plugin;
+import org.apache.qpid.server.security.access.ObjectProperties;
+import org.apache.qpid.server.security.access.ObjectType;
+import org.apache.qpid.server.security.access.Operation;
+
+/**
+ * The two methods, {@link #access(ObjectType, Object)} and {@link #authorise(Operation, ObjectType, ObjectProperties)},
+ * return the {@link Result} of the security decision, which may be to {@link Result#ABSTAIN} if no decision is made
+ * by this plugin.
+ */
+public interface SecurityPlugin extends Plugin
+{
+ /**
+ * Default result for {@link #access(ObjectType, Object)} or {@link #authorise(Operation, ObjectType, ObjectProperties)}.
+ */
+ Result getDefault();
+
+ /**
+ * Authorise access granted to an object instance.
+ */
+ Result access(ObjectType objectType, Object instance);
+
+ /**
+ * Authorise an operation on an object defined by a set of properties.
+ */
+ Result authorise(Operation operation, ObjectType objectType, ObjectProperties properties);
+}
Added: qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/SecurityPluginActivator.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/SecurityPluginActivator.java?rev=949781&view=auto
==============================================================================
--- qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/SecurityPluginActivator.java (added)
+++ qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/SecurityPluginActivator.java Mon May 31 16:03:41 2010
@@ -0,0 +1,54 @@
+package org.apache.qpid.server.security;
+
+import org.apache.log4j.Logger;
+import org.apache.qpid.server.configuration.plugins.ConfigurationPluginFactory;
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+
+/**
+ * An OSGi {@link BundleActivator} that loads a {@link SecurityPluginFactory}.
+ */
+public abstract class SecurityPluginActivator implements BundleActivator
+{
+ private static final Logger _logger = Logger.getLogger(SecurityPluginActivator.class);
+
+ private SecurityPluginFactory _factory;
+ private ConfigurationPluginFactory _config;
+ private BundleContext _ctx;
+ private String _bundleName;
+
+ /** Implement this to return the factory this plugin activates. */
+ public abstract SecurityPluginFactory getFactory();
+
+ /** Implement this to return the factory this plugin activates. */
+ public abstract ConfigurationPluginFactory getConfigurationFactory();
+
+ /**
+ * @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext)
+ */
+ public void start(BundleContext ctx) throws Exception
+ {
+ _ctx = ctx;
+ _factory = getFactory();
+ _config = getConfigurationFactory();
+ _bundleName = ctx.getBundle().getSymbolicName();
+
+ // register the service
+ _logger.info("Registering security plugin: " + _bundleName);
+ _ctx.registerService(SecurityPluginFactory.class.getName(), _factory, null);
+ _ctx.registerService(ConfigurationPluginFactory.class.getName(), _config, null);
+ }
+
+ /**
+ * @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext)
+ */
+ public void stop(BundleContext context) throws Exception
+ {
+ _logger.info("Stopping security plugin: " + _bundleName);
+
+ // null object references
+ _factory = null;
+ _config = null;
+ _ctx = null;
+ }
+}
Copied: qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/SecurityPluginFactory.java (from r949780, qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/AuthorizationManager.java)
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/SecurityPluginFactory.java?p2=qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/SecurityPluginFactory.java&p1=qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/AuthorizationManager.java&r1=949780&r2=949781&rev=949781&view=diff
==============================================================================
--- qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/AuthorizationManager.java (original)
+++ qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/SecurityPluginFactory.java Mon May 31 16:03:41 2010
@@ -1,6 +1,5 @@
-package org.apache.qpid.server.security.access;
/*
- *
+ *
* 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
@@ -8,20 +7,24 @@ package org.apache.qpid.server.security.
* 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.qpid.server.security;
+import org.apache.qpid.server.plugins.PluginFactory;
-public class AuthorizationManager
+/**
+ * The factory that generates instances of security plugins. Usually implemented as a static member class in the plugin itself.
+ */
+public interface SecurityPluginFactory<S extends SecurityPlugin> extends PluginFactory<S>
{
-
}
Added: qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/ObjectProperties.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/ObjectProperties.java?rev=949781&view=auto
==============================================================================
--- qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/ObjectProperties.java (added)
+++ qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/ObjectProperties.java Mon May 31 16:03:41 2010
@@ -0,0 +1,315 @@
+/*
+ * 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.qpid.server.security.access;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.qpid.framing.AMQShortString;
+import org.apache.qpid.server.exchange.Exchange;
+import org.apache.qpid.server.queue.AMQQueue;
+
+/**
+ * An set of properties for an access control v2 rule {@link ObjectType}.
+ *
+ * The {@link #matches(ObjectProperties)} method is intended to be used when determining precedence of rules, and
+ * {@link #equals(Object)} and {@link #hashCode()} are intended for use in maps. This is due to the wildcard matching
+ * described above.
+ */
+public class ObjectProperties extends HashMap<ObjectProperties.Property, String>
+{
+ /** serialVersionUID */
+ private static final long serialVersionUID = -1356019341374170495L;
+
+ public static final String STAR= "*";
+
+ public static final ObjectProperties EMPTY = new ObjectProperties();
+
+ public enum Property
+ {
+ ROUTING_KEY,
+ NAME,
+ QUEUE_NAME,
+ OWNER,
+ TYPE,
+ ALTERNATE,
+ IMMEDIATE,
+ INTERNAL,
+ NO_WAIT,
+ NO_LOCAL,
+ NO_ACK,
+ PASSIVE,
+ DURABLE,
+ EXCLUSIVE,
+ TEMPORARY,
+ AUTO_DELETE,
+ COMPONENT,
+ PACKAGE,
+ CLASS;
+
+ public static Property parse(String text)
+ {
+ for (Property property : values())
+ {
+ if (property.getName().equalsIgnoreCase(text))
+ {
+ return property;
+ }
+ }
+ throw new IllegalArgumentException("Not a valid property: " + text);
+ }
+
+ public String getName()
+ {
+ return StringUtils.remove(name(), '_').toLowerCase();
+ }
+
+ public static List<String> getPropertyNames()
+ {
+ List<String> properties = new ArrayList<String>();
+ for (Property property : values())
+ {
+ properties.add(property.getName());
+ }
+ return properties;
+ }
+ }
+
+ public static List<String> getAllPropertyNames()
+ {
+ List<String> properties = new ArrayList<String>();
+ for (Property property : Property.values())
+ {
+ properties.add(StringUtils.remove(property.name(), '_').toLowerCase());
+ }
+ return properties;
+ }
+
+ public ObjectProperties()
+ {
+ super();
+ }
+
+ public ObjectProperties(ObjectProperties copy)
+ {
+ super();
+
+ putAll(copy);
+ }
+
+ public ObjectProperties(String name)
+ {
+ super();
+
+ setName(name);
+ }
+
+
+ public ObjectProperties(AMQShortString name)
+ {
+ super();
+
+ setName(name);
+ }
+
+ public ObjectProperties(AMQQueue queue)
+ {
+ super();
+
+ setName(queue.getName());
+
+ put(Property.AUTO_DELETE, queue.isAutoDelete());
+ put(Property.TEMPORARY, queue.isAutoDelete());
+ put(Property.DURABLE, queue.isDurable());
+ put(Property.EXCLUSIVE, queue.isExclusive());
+ if (queue.getAlternateExchange() != null)
+ {
+ put(Property.ALTERNATE, queue.getAlternateExchange().getName());
+ }
+ if (queue.getOwner() != null)
+ {
+ put(Property.OWNER, queue.getOwner());
+ }
+ else if (queue.getPrincipalHolder() != null)
+ {
+ put(Property.OWNER, queue.getPrincipalHolder().getPrincipal().getName());
+ }
+ }
+
+ public ObjectProperties(Exchange exch, AMQQueue queue, AMQShortString routingKey)
+ {
+ this(queue);
+
+ setName(exch.getName());
+
+ put(Property.QUEUE_NAME, queue.getName());
+ put(Property.ROUTING_KEY, routingKey);
+ }
+
+ public ObjectProperties(Exchange exch, AMQShortString routingKey)
+ {
+ this(exch.getName(), routingKey.asString());
+ }
+
+ public ObjectProperties(String exchangeName, String routingKey, Boolean immediate)
+ {
+ this(exchangeName, routingKey);
+
+ put(Property.IMMEDIATE, immediate);
+ }
+
+ public ObjectProperties(String exchangeName, String routingKey)
+ {
+ super();
+
+ setName(exchangeName);
+
+ put(Property.ROUTING_KEY, routingKey);
+ }
+
+ public ObjectProperties(Boolean autoDelete, Boolean durable, AMQShortString exchangeName,
+ Boolean internal, Boolean nowait, Boolean passive, AMQShortString exchangeType)
+ {
+ super();
+
+ setName(exchangeName);
+
+ put(Property.AUTO_DELETE, autoDelete);
+ put(Property.TEMPORARY, autoDelete);
+ put(Property.DURABLE, durable);
+ put(Property.INTERNAL, internal);
+ put(Property.NO_WAIT, nowait);
+ put(Property.PASSIVE, passive);
+ put(Property.TYPE, exchangeType);
+ }
+
+ public ObjectProperties(Boolean autoDelete, Boolean durable, Boolean exclusive, Boolean nowait, Boolean passive,
+ AMQShortString queueName, String owner)
+ {
+ super();
+
+ setName(queueName);
+
+ put(Property.AUTO_DELETE, autoDelete);
+ put(Property.TEMPORARY, autoDelete);
+ put(Property.DURABLE, durable);
+ put(Property.EXCLUSIVE, exclusive);
+ put(Property.NO_WAIT, nowait);
+ put(Property.PASSIVE, passive);
+ put(Property.OWNER, owner);
+ }
+
+ public ObjectProperties(Boolean exclusive, Boolean noAck, Boolean noLocal, Boolean nowait, AMQQueue queue)
+ {
+ this(queue);
+
+ put(Property.NO_LOCAL, noLocal);
+ put(Property.NO_ACK, noAck);
+ put(Property.EXCLUSIVE, exclusive);
+ put(Property.NO_WAIT, nowait);
+ }
+
+ public List<String> getPropertyNames()
+ {
+ List<String> properties = new ArrayList<String>();
+ for (Property property : keySet())
+ {
+ properties.add(property.getName());
+ }
+ return properties;
+ }
+
+ public Boolean isSet(Property key)
+ {
+ return containsKey(key) && Boolean.valueOf(get(key));
+ }
+
+ public String getName()
+ {
+ return get(Property.NAME);
+ }
+
+ public void setName(String name)
+ {
+ put(Property.NAME, name);
+ }
+
+ public void setName(AMQShortString name)
+ {
+ put(Property.NAME, name);
+ }
+
+ public String put(Property key, AMQShortString value)
+ {
+ return put(key, value == null ? "" : value.asString());
+ }
+
+ @Override
+ public String put(Property key, String value)
+ {
+ return super.put(key, value == null ? "" : value.trim());
+ }
+
+ public void put(Property key, Boolean value)
+ {
+ if (value != null)
+ {
+ super.put(key, Boolean.toString(value));
+ }
+ }
+
+ public boolean matches(ObjectProperties properties)
+ {
+ if (properties.keySet().isEmpty())
+ {
+ return true;
+ }
+
+ if (!keySet().containsAll(properties.keySet()))
+ {
+ return false;
+ }
+
+ for (Property key : properties.keySet())
+ {
+ String ruleValue = properties.get(key);
+ String thisValue = get(key);
+
+ if (!valueMatches(thisValue, ruleValue))
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ private boolean valueMatches(String thisValue, String ruleValue)
+ {
+ return (StringUtils.isEmpty(ruleValue)
+ || StringUtils.equals(thisValue, ruleValue))
+ || ruleValue.equals(STAR)
+ || (ruleValue.endsWith(STAR)
+ && thisValue != null
+ && thisValue.length() > ruleValue.length()
+ && thisValue.startsWith(ruleValue.substring(0, ruleValue.length() - 2)));
+ }
+}
Added: qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/ObjectType.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/ObjectType.java?rev=949781&view=auto
==============================================================================
--- qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/ObjectType.java (added)
+++ qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/ObjectType.java Mon May 31 16:03:41 2010
@@ -0,0 +1,90 @@
+/*
+ * 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.qpid.server.security.access;
+
+import static org.apache.qpid.server.security.access.Operation.*;
+
+import java.util.EnumSet;
+import java.util.Set;
+
+/**
+ * An enumeration of all possible object types that can form part of an access control v2 rule.
+ *
+ * Each object type is valid only for a certain set of {@link Operation}s, which are passed as a list to
+ * the constructor, and can be checked using the {@link #isAllowed(Operation)} method.
+ */
+public enum ObjectType
+{
+ ALL(Operation.ALL),
+ VIRTUALHOST(ACCESS),
+ QUEUE(CREATE, DELETE, PURGE, CONSUME),
+ TOPIC(CREATE, DELETE, PURGE, CONSUME),
+ EXCHANGE(ACCESS, CREATE, DELETE, BIND, UNBIND, PUBLISH),
+ BROKER(ACCESS),
+ LINK, // Not allowed in the Java broker
+ ROUTE, // Not allowed in the Java broker
+ METHOD(Operation.ALL, ACCESS, UPDATE, EXECUTE),
+ OBJECT(ACCESS);
+
+ private EnumSet<Operation> _actions;
+
+ private ObjectType()
+ {
+ _actions = EnumSet.noneOf(Operation.class);
+ }
+
+ private ObjectType(Operation operation)
+ {
+ if (operation == Operation.ALL)
+ {
+ _actions = EnumSet.allOf(Operation.class);
+ }
+ else
+ {
+ _actions = EnumSet.of(operation);
+ }
+ }
+
+ private ObjectType(Operation first, Operation...rest)
+ {
+ _actions = EnumSet.of(first, rest);
+ }
+
+ public Set<Operation> getActions()
+ {
+ return _actions;
+ }
+
+ public boolean isAllowed(Operation operation)
+ {
+ return _actions.contains(operation);
+ }
+
+ public static ObjectType parse(String text)
+ {
+ for (ObjectType object : values())
+ {
+ if (object.name().equalsIgnoreCase(text))
+ {
+ return object;
+ }
+ }
+ throw new IllegalArgumentException("Not a valid object type: " + text);
+ }
+}
Copied: qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/Operation.java (from r949780, qpid/trunk/qpid/java/broker/src/test/java/org/apache/qpid/server/security/access/ExchangeDenier.java)
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/Operation.java?p2=qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/Operation.java&p1=qpid/trunk/qpid/java/broker/src/test/java/org/apache/qpid/server/security/access/ExchangeDenier.java&r1=949780&r2=949781&rev=949781&view=diff
==============================================================================
--- qpid/trunk/qpid/java/broker/src/test/java/org/apache/qpid/server/security/access/ExchangeDenier.java (original)
+++ qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/Operation.java Mon May 31 16:03:41 2010
@@ -15,35 +15,35 @@
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
- *
- *
*/
package org.apache.qpid.server.security.access;
-import org.apache.commons.configuration.Configuration;
-import org.apache.qpid.server.exchange.Exchange;
-import org.apache.qpid.server.security.access.plugins.AllowAll;
-import org.apache.qpid.server.security.PrincipalHolder;
-
-public class ExchangeDenier extends AllowAll
+/**
+ * An enumeration of all possible actions that can form part of an access control v2 rule.
+ */
+public enum Operation
{
-
- public static final ACLPluginFactory FACTORY = new ACLPluginFactory()
+ ALL,
+ CONSUME,
+ PUBLISH,
+ CREATE,
+ ACCESS,
+ BIND,
+ UNBIND,
+ DELETE,
+ PURGE,
+ UPDATE,
+ EXECUTE;
+
+ public static Operation parse(String text)
{
- public boolean supportsTag(String name)
- {
- return name.startsWith("exchangeDenier");
- }
-
- public ACLPlugin newInstance(Configuration config)
+ for (Operation operation : values())
{
- return new ExchangeDenier();
+ if (operation.name().equalsIgnoreCase(text))
+ {
+ return operation;
+ }
}
- };
-
- @Override
- public AuthzResult authoriseDelete(PrincipalHolder session, Exchange exchange)
- {
- return AuthzResult.DENIED;
+ throw new IllegalArgumentException("Not a valid operation: " + text);
}
-}
+}
\ No newline at end of file
Modified: qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/Permission.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/Permission.java?rev=949781&r1=949780&r2=949781&view=diff
==============================================================================
--- qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/Permission.java (original)
+++ qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/Permission.java Mon May 31 16:03:41 2010
@@ -20,19 +20,28 @@
*/
package org.apache.qpid.server.security.access;
-import org.apache.qpid.framing.AMQShortString;
-import org.apache.qpid.server.exchange.Exchange;
-import org.apache.qpid.server.queue.AMQQueue;
+import org.apache.commons.lang.StringUtils;
+/**
+ * An enumeration of all possible permissions that can be applied to an access control v2 rule.
+ */
public enum Permission
{
- CONSUME,
- PUBLISH,
- CREATEQUEUE,
- CREATEEXCHANGE,
- ACCESS,
- BIND,
- UNBIND,
- DELETE,
- PURGE
-}
+ ALLOW,
+ ALLOW_LOG,
+ DENY,
+ DENY_LOG;
+
+ public static Permission parse(String text)
+ {
+
+ for (Permission permission : values())
+ {
+ if (permission.name().equalsIgnoreCase(StringUtils.replaceChars(text, '-', '_')))
+ {
+ return permission;
+ }
+ }
+ throw new IllegalArgumentException("Not a valid permission: " + text);
+ }
+}
\ No newline at end of file
Modified: qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/plugins/AllowAll.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/plugins/AllowAll.java?rev=949781&r1=949780&r2=949781&view=diff
==============================================================================
--- qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/plugins/AllowAll.java (original)
+++ qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/plugins/AllowAll.java Mon May 31 16:03:41 2010
@@ -15,40 +15,72 @@
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
- *
- *
*/
package org.apache.qpid.server.security.access.plugins;
+import java.util.Arrays;
+import java.util.List;
+
import org.apache.commons.configuration.Configuration;
-import org.apache.qpid.server.security.access.ACLPlugin;
-import org.apache.qpid.server.security.access.ACLPluginFactory;
+import org.apache.commons.configuration.ConfigurationException;
+import org.apache.qpid.server.configuration.plugins.ConfigurationPlugin;
+import org.apache.qpid.server.configuration.plugins.ConfigurationPluginFactory;
+import org.apache.qpid.server.security.Result;
+import org.apache.qpid.server.security.SecurityPluginFactory;
-public class AllowAll extends BasicACLPlugin
+/** Always allow. */
+public class AllowAll extends BasicPlugin
{
-
- public static final ACLPluginFactory FACTORY = new ACLPluginFactory()
+ public static class AllowAllConfiguration extends ConfigurationPlugin {
+ public static final ConfigurationPluginFactory FACTORY = new ConfigurationPluginFactory()
+ {
+ public List<String> getParentPaths()
+ {
+ return Arrays.asList("security", "virtualhosts.virtualhost.security");
+ }
+
+ public ConfigurationPlugin newInstance(String path, Configuration config) throws ConfigurationException
+ {
+ ConfigurationPlugin instance = new AllowAllConfiguration();
+ instance.setConfiguration(path, config);
+ return instance;
+ }
+ };
+
+ public String[] getElementsProcessed()
+ {
+ return new String[] { "allow-all" };
+ }
+ }
+
+ public static final SecurityPluginFactory<AllowAll> FACTORY = new SecurityPluginFactory<AllowAll>()
{
- public boolean supportsTag(String name)
+ public AllowAll newInstance(ConfigurationPlugin config) throws ConfigurationException
{
- return false;
+ AllowAll plugin = new AllowAll(config);
+ plugin.configure();
+ return plugin;
}
- public ACLPlugin newInstance(Configuration config)
+ public String getPluginName()
{
- return new AllowAll();
+ return AllowAll.class.getName();
}
- };
- public String getPluginName()
- {
- return this.getClass().getSimpleName();
+ public Class<AllowAll> getPluginClass()
+ {
+ return AllowAll.class;
+ }
+ };
+
+ @Override
+ public Result getDefault()
+ {
+ return Result.ALLOWED;
}
- @Override
- protected AuthzResult getResult()
+ public AllowAll(ConfigurationPlugin config)
{
- // Always allow
- return AuthzResult.ALLOWED;
+ _config = config.getConfiguration(AllowAllConfiguration.class);
}
}
Added: qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/plugins/BasicPlugin.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/plugins/BasicPlugin.java?rev=949781&view=auto
==============================================================================
--- qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/plugins/BasicPlugin.java (added)
+++ qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/plugins/BasicPlugin.java Mon May 31 16:03:41 2010
@@ -0,0 +1,51 @@
+/*
+ *
+ * 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.qpid.server.security.access.plugins;
+
+import org.apache.commons.configuration.ConfigurationException;
+import org.apache.qpid.server.security.AbstractPlugin;
+import org.apache.qpid.server.security.Result;
+import org.apache.qpid.server.security.SecurityPlugin;
+import org.apache.qpid.server.security.access.ObjectProperties;
+import org.apache.qpid.server.security.access.ObjectType;
+import org.apache.qpid.server.security.access.Operation;
+
+/**
+ * This {@link SecurityPlugin} simply abstains from all authorisation requests and ignores configuration.
+ */
+public class BasicPlugin extends AbstractPlugin
+{
+ public Result access(ObjectType objectType, Object instance)
+ {
+ return getDefault();
+ }
+
+ public Result authorise(Operation operation, ObjectType objectType, ObjectProperties properties)
+ {
+ return getDefault();
+ }
+
+ @Override
+ public void configure() throws ConfigurationException
+ {
+ // Not used
+ }
+}
---------------------------------------------------------------------
Apache Qpid - AMQP Messaging Implementation
Project: http://qpid.apache.org
Use/Interact: mailto:commits-subscribe@qpid.apache.org