This closes #539

This commit is contained in:
Clebert Suconic 2016-05-25 09:33:56 -04:00
commit 4834c2a59e
5 changed files with 121 additions and 19 deletions

View File

@ -65,14 +65,14 @@ under the License.
<security-settings>
<security-setting match="#">
<permission type="createNonDurableQueue" roles="amq"/>
<permission type="deleteNonDurableQueue" roles="amq"/>
<permission type="createDurableQueue" roles="amq"/>
<permission type="deleteDurableQueue" roles="amq"/>
<permission type="consume" roles="amq"/>
<permission type="send" roles="amq"/>
<permission type="createNonDurableQueue" roles="manager"/>
<permission type="deleteNonDurableQueue" roles="manager"/>
<permission type="createDurableQueue" roles="manager"/>
<permission type="deleteDurableQueue" roles="manager"/>
<permission type="consume" roles="manager"/>
<permission type="send" roles="manager"/>
<!-- we need this otherwise ./artemis data imp wouldn't work -->
<permission type="manage" roles="amq"/>
<permission type="manage" roles="manager"/>
</security-setting>
</security-settings>
@ -85,6 +85,7 @@ under the License.
<max-size-bytes>10485760</max-size-bytes>
<message-counter-history-day-limit>10</message-counter-history-day-limit>
<address-full-policy>BLOCK</address-full-policy>
<auto-create-jms-queues>true</auto-create-jms-queues>
</address-setting>
</address-settings>
</core>

View File

@ -1,3 +1,4 @@
config=file:etc/artemis.xml
name=local
domain=local
domain=karaf
rolePrincipalClass=org.apache.karaf.jaas.boot.principal.RolePrincipal

View File

@ -50,6 +50,7 @@ import org.osgi.util.tracker.ServiceTracker;
public class OsgiBroker {
private String name;
private String configurationUrl;
private String rolePrincipalClass;
private Map<String, ActiveMQComponent> components;
private Map<String, ServiceRegistration<?>> registrations;
private ServiceTracker tracker;
@ -60,8 +61,12 @@ public class OsgiBroker {
final Dictionary<String, Object> properties = cctx.getProperties();
configurationUrl = getMandatory(properties, "config");
name = getMandatory(properties, "name");
rolePrincipalClass = (String)properties.get("rolePrincipalClass");
String domain = getMandatory(properties, "domain");
ActiveMQJAASSecurityManager security = new ActiveMQJAASSecurityManager(domain);
if (rolePrincipalClass != null) {
security.setRolePrincipalClass(rolePrincipalClass);
}
String brokerInstance = null;
String karafDataDir = System.getProperty("karaf.data");
if (karafDataDir != null) {

View File

@ -20,6 +20,8 @@ import javax.security.auth.Subject;
import javax.security.auth.login.LoginContext;
import javax.security.auth.login.LoginException;
import javax.security.cert.X509Certificate;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.security.Principal;
import java.util.HashSet;
import java.util.Iterator;
@ -45,8 +47,11 @@ public class ActiveMQJAASSecurityManager implements ActiveMQSecurityManager2 {
private static final Logger logger = Logger.getLogger(ActiveMQJAASSecurityManager.class);
private static final String WILDCARD = "*";
private String configurationName;
private SecurityConfiguration configuration;
private String rolePrincipalClass = "org.apache.activemq.artemis.spi.core.security.jaas.RolePrincipal";
public ActiveMQJAASSecurityManager() {
}
@ -72,7 +77,10 @@ public class ActiveMQJAASSecurityManager implements ActiveMQSecurityManager2 {
return true;
}
catch (LoginException e) {
logger.debug("Couldn't validate user", e);
logger.info("Couldn't validate user: " + e.getMessage());
if (logger.isDebugEnabled()) {
logger.debug("Couldn't validate user", e);
}
return false;
}
}
@ -108,9 +116,15 @@ public class ActiveMQJAASSecurityManager implements ActiveMQSecurityManager2 {
Set<RolePrincipal> rolesWithPermission = getPrincipalsInRole(checkType, roles);
// Check the caller's roles
Set<RolePrincipal> rolesForSubject = localSubject.getPrincipals(RolePrincipal.class);
Set<Principal> rolesForSubject = new HashSet<Principal>();
try {
rolesForSubject.addAll(localSubject.getPrincipals(Class.forName(rolePrincipalClass).asSubclass(Principal.class)));
}
catch (Exception e) {
logger.info("Can't find roles for the subject", e);
}
if (rolesForSubject.size() > 0 && rolesWithPermission.size() > 0) {
Iterator<RolePrincipal> rolesForSubjectIter = rolesForSubject.iterator();
Iterator<Principal> rolesForSubjectIter = rolesForSubject.iterator();
while (!authorized && rolesForSubjectIter.hasNext()) {
Iterator<RolePrincipal> rolesWithPermissionIter = rolesWithPermission.iterator();
Principal subjectRole = rolesForSubjectIter.next();
@ -136,10 +150,15 @@ public class ActiveMQJAASSecurityManager implements ActiveMQSecurityManager2 {
}
private Set<RolePrincipal> getPrincipalsInRole(final CheckType checkType, final Set<Role> roles) {
Set<RolePrincipal> principals = new HashSet<>();
Set principals = new HashSet<>();
for (Role role : roles) {
if (checkType.hasRole(role)) {
principals.add(new RolePrincipal(role.getName()));
try {
principals.add(createGroupPrincipal(role.getName(), rolePrincipalClass));
}
catch (Exception e) {
logger.info("Can't add role principal", e);
}
}
}
return principals;
@ -160,4 +179,71 @@ public class ActiveMQJAASSecurityManager implements ActiveMQSecurityManager2 {
return configuration;
}
public String getRolePrincipalClass() {
return rolePrincipalClass;
}
public void setRolePrincipalClass(String rolePrincipalClass) {
this.rolePrincipalClass = rolePrincipalClass;
}
public static Object createGroupPrincipal(String name, String groupClass) throws Exception {
if (WILDCARD.equals(name)) {
// simple match all group principal - match any name and class
return new Principal() {
@Override
public String getName() {
return WILDCARD;
}
@Override
public boolean equals(Object other) {
return true;
}
@Override
public int hashCode() {
return WILDCARD.hashCode();
}
};
}
Object[] param = new Object[]{name};
Class<?> cls = Class.forName(groupClass);
Constructor<?>[] constructors = cls.getConstructors();
int i;
Object instance;
for (i = 0; i < constructors.length; i++) {
Class<?>[] paramTypes = constructors[i].getParameterTypes();
if (paramTypes.length != 0 && paramTypes[0].equals(String.class)) {
break;
}
}
if (i < constructors.length) {
instance = constructors[i].newInstance(param);
}
else {
instance = cls.newInstance();
Method[] methods = cls.getMethods();
i = 0;
for (i = 0; i < methods.length; i++) {
Class<?>[] paramTypes = methods[i].getParameterTypes();
if (paramTypes.length != 0 && methods[i].getName().equals("setName") && paramTypes[0].equals(String.class)) {
break;
}
}
if (i < methods.length) {
methods[i].invoke(instance, param);
}
else {
throw new NoSuchMethodException();
}
}
return instance;
}
}

View File

@ -40,6 +40,11 @@ import org.osgi.framework.InvalidSyntaxException;
import org.osgi.util.tracker.ServiceTracker;
import javax.inject.Inject;
import javax.jms.Connection;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.MessageProducer;
import javax.jms.Queue;
import javax.security.auth.Subject;
import java.io.ByteArrayOutputStream;
import java.io.File;
@ -137,13 +142,17 @@ public class ArtemisFeatureTest extends Assert {
String amqpURI = "amqp://localhost:5672";
JmsConnectionFactory factory = new JmsConnectionFactory(amqpURI);
factory.setUsername(USER);
factory.setPassword(PASSWORD);
Connection connection = factory.createConnection(USER, PASSWORD);
connection.start();
//TODO fix security settings and test sending/receiving messages
/*
Connection connection = factory.createConnection();
connection.start();*/
javax.jms.Session sess = connection.createSession(false, javax.jms.Session.AUTO_ACKNOWLEDGE);
Queue queue = sess.createQueue("jms.queue.exampleQueue");
MessageProducer producer = sess.createProducer(queue);
producer.send(sess.createTextMessage("TEST"));
MessageConsumer consumer = sess.createConsumer(queue);
Message msg = consumer.receive(5000);
assertNotNull(msg);
}
protected String executeCommand(final String command, final Long timeout, final Boolean silent) {