org.apache.activemq.shiro.authz.DestinationActionPermissionResolver Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of activemq-shiro Show documentation
Show all versions of activemq-shiro Show documentation
ActiveMQ secured by Apache Shiro
/**
* 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.shiro.authz;
import org.apache.activemq.command.ActiveMQDestination;
import org.apache.shiro.authz.Permission;
import org.apache.shiro.authz.permission.WildcardPermission;
import java.util.Collection;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Set;
/**
* A {@code DestinationActionPermissionResolver} inspects {@link DestinationAction}s and returns one or more
* {@link WildcardPermission}s that must be granted to a {@code Subject} in order for that {@code Subject} to
* perform the action being taken on an {@link ActiveMQDestination}.
*
* See the {@link #createPermissionString createPermissionString documentation} to see what the
* resulting {@link WildcardPermission} instances would look like.
*
* @see #createPermissionString(org.apache.activemq.command.ActiveMQDestination, String) )
* @see #setPermissionStringPrefix(String)
* @since 5.10.0
*/
public class DestinationActionPermissionResolver implements ActionPermissionResolver {
private String permissionStringPrefix;
private boolean permissionStringCaseSensitive = true;
/**
* Returns the String prefix that should be automatically prepended to a permission String before the
* String is converted to a {@link WildcardPermission} instance. This is convenient if you want to provide a
* 'scope' or 'namespace' for ActiveMQ Destinations to clearly distinguish ActiveMQ-specific permissions from any
* others you might assign to user accounts. The default value is {@code null}, indicating no prefix will be
* set by default.
*
* For example, the default settings might result in permissions Strings that look like this:
*
* topic:TEST:create
* temp-queue:MyQueue:remove
* topic:ActiveMQ.Advisory.*:read
*
*
* However, if your application has any application-specific permissions that start with the tokens {@code topic},
* {@code temp-topic}, {@code queue}, or {@code temp-queue}, you wouldn't be able to distinguish between
* application-specific permissions and those specific to ActiveMQ. In this case you might set the
* {@code permissionStringPrefix}. For example, if you set:
* {@code resolver.setPermissionStringPrefix("jms");}, the above permission strings would look like this:
*
* jms:topic:TEST:create
* jms:temp-queue:MyQueue:remove
* jms:topic:ActiveMQ.Advisory.*:read
*
*
* Similarly, if the {@code permissionStringPrefix} was equal to {@code activeMQ}:
*
* activeMQ:topic:TEST:create
* activeMQ:temp-queue:MyQueue:remove
* activeMQ:topic:ActiveMQ.Advisory.*:read
*
*
* @return any String prefix that should be automatically prepended to a permission String before the
* String is converted to a {@link WildcardPermission} instance. Useful for namespacing permissions.
*/
public String getPermissionStringPrefix() {
return permissionStringPrefix;
}
/**
* Sets the String prefix that should be automatically prepended to a permission String before the
* String is converted to a {@link WildcardPermission} instance. This is convenient if you want to provide a
* 'scope' or 'namespace' for ActiveMQ Destinations to clearly distinguish ActiveMQ-specific permissions from any
* others you might assign to user accounts. The default value is {@code null}, indicating no prefix will be
* set by default.
*
* For example, the default settings might result in permissions Strings that look like this:
*
* topic:TEST:create
* temp-queue:MyQueue:remove
* topic:ActiveMQ.Advisory.*:read
*
*
* However, if your application has any application-specific permissions that start with the tokens {@code topic},
* {@code temp-topic}, {@code queue}, or {@code temp-queue}, you wouldn't be able to distinguish between
* application-specific permissions and those specific to ActiveMQ. In this case you might set the
* {@code permissionStringPrefix}. For example, if you set:
* {@code resolver.setPermissionStringPrefix("jms");}, the above permission strings would look like this:
*
* jms:topic:TEST:create
* jms:temp-queue:MyQueue:remove
* jms:topic:ActiveMQ.Advisory.*:read
*
*
* Similarly, if the {@code permissionStringPrefix} was equal to {@code activeMQ}:
*
* activeMQ:topic:TEST:create
* activeMQ:temp-queue:MyQueue:remove
* activeMQ:topic:ActiveMQ.Advisory.*:read
*
*
* @param permissionStringPrefix any String prefix that should be automatically prepended to a permission String
* before the String is converted to a {@link WildcardPermission} instance. Useful
* for namespacing permissions.
*/
public void setPermissionStringPrefix(String permissionStringPrefix) {
this.permissionStringPrefix = permissionStringPrefix;
}
/**
* Returns {@code true} if returned {@link WildcardPermission} instances should be considered case-sensitive,
* {@code false} otherwise. The default value is {@code true}, which is not the normal
* {@link WildcardPermission} default setting. This default was chosen to reflect ActiveMQ's
* case-sensitive destination names.
*
* @return {@code true} if returned {@link WildcardPermission} instances should be considered case-sensitive,
* {@code false} otherwise.
*/
public boolean isPermissionStringCaseSensitive() {
return permissionStringCaseSensitive;
}
/**
* Sets whether returned {@link WildcardPermission} instances should be considered case-sensitive.
* The default value is {@code true}, which is not the normal
* {@link WildcardPermission} default setting. This default was chosen to accurately reflect ActiveMQ's
* case-sensitive destination names.
*
* @param permissionStringCaseSensitive whether returned {@link WildcardPermission} instances should be considered
* case-sensitive.
*/
public void setPermissionStringCaseSensitive(boolean permissionStringCaseSensitive) {
this.permissionStringCaseSensitive = permissionStringCaseSensitive;
}
@Override
public Collection getPermissions(Action action) {
if (!(action instanceof DestinationAction)) {
throw new IllegalArgumentException("Action argument must be a " + DestinationAction.class.getName() + " instance.");
}
DestinationAction da = (DestinationAction) action;
return getPermissions(da);
}
protected Collection getPermissions(DestinationAction da) {
ActiveMQDestination dest = da.getDestination();
String verb = da.getVerb();
return createPermissions(dest, verb);
}
protected Collection createPermissions(ActiveMQDestination dest, String verb) {
Set set;
if (dest.isComposite()) {
ActiveMQDestination[] composites = dest.getCompositeDestinations();
set = new LinkedHashSet(composites.length);
for(ActiveMQDestination d : composites) {
Collection perms = createPermissions(d, verb);
set.addAll(perms);
}
} else {
set = new HashSet(1);
String permString = createPermissionString(dest, verb);
Permission perm = createPermission(permString);
set.add(perm);
}
return set;
}
/**
* Inspects the specified {@code destination} and {@code verb} and returns a {@link WildcardPermission}-compatible
* String the represents the action.
* Format
* This implementation returns WildcardPermission strings with the following format:
*
* optionalPermissionStringPrefix + destinationType + ':' + destinationPhysicalName + ':' + actionVerb
*
* where:
*
* - {@code optionalPermissionStringPrefix} is the {@link #getPermissionStringPrefix() permissionStringPrefix}
* followed by a colon delimiter (':'). This is only present if the {@code permissionStringPrefix} has been
* specified and is non-null
* - {@code destinationType} is one of the following four string tokens:
*
* - {@code topic}
* - {@code temp-topic}
* - {@code queue}
* - {@code temp-queue}
*
* based on whether the {@link DestinationAction#getDestination() destination} is
* a topic, temporary topic, queue, or temporary queue (respectively).
*
* -
* {@code destinationPhysicalName} is
* {@link org.apache.activemq.command.ActiveMQDestination#getPhysicalName() destination.getPhysicalName()}
*
* -
* {@code actionVerb} is {@link DestinationAction#getVerb() action.getVerb()}
*
*
* Examples
* With the default settings (no {@link #getPermissionStringPrefix() permissionStringPrefix}), this might produce
* strings that look like the following:
*
* topic:TEST:create
* temp-queue:MyTempQueue:remove
* queue:ActiveMQ.Advisory.*:read
*
* If {@link #getPermissionStringPrefix() permissionStringPrefix} was set to {@code jms}, the above examples would
* look like this:
*
* jms:topic:TEST:create
* jms:temp-queue:MyTempQueue:remove
* jms:queue:ActiveMQ.Advisory.*:read
*
*
* @param dest the destination to inspect and convert to a {@link WildcardPermission} string.
* @param verb the behavior taken on the destination
* @return a {@link WildcardPermission} string that represents the specified {@code action}.
* @see #getPermissionStringPrefix() getPermissionStringPrefix() for more on why you might want to set this value
*/
protected String createPermissionString(ActiveMQDestination dest, String verb) {
if (dest.isComposite()) {
throw new IllegalArgumentException("Use createPermissionStrings for composite destinations.");
}
StringBuilder sb = new StringBuilder();
if (permissionStringPrefix != null) {
sb.append(permissionStringPrefix);
if (!permissionStringPrefix.endsWith(":")) {
sb.append(":");
}
}
if (dest.isTemporary()) {
sb.append("temp-");
}
if (dest.isTopic()) {
sb.append("topic:");
} else {
sb.append("queue:");
}
sb.append(dest.getPhysicalName());
sb.append(':');
sb.append(verb);
return sb.toString();
}
protected Permission createPermission(String permissionString) {
return new ActiveMQWildcardPermission(permissionString, isPermissionStringCaseSensitive());
}
}