Added trivial implementation of ACL patterns

This commit is contained in:
andrea
2015-05-26 22:40:34 +02:00
parent 092e30a552
commit db4b7ca192
9 changed files with 73 additions and 42 deletions
@@ -299,7 +299,7 @@ class ProtocolProcessor implements EventHandler<ValueEvent> {
boolean retain = msg.isRetainFlag();
//check if the topic can be wrote
String user = (String) session.getAttribute(NettyChannel.ATTR_KEY_USERNAME);
if (m_authorizator.canWrite(topic, user)) {
if (m_authorizator.canWrite(topic, user, clientID)) {
processPublish(clientID, topic, qos, message, retain, msg.getMessageID());
} else {
LOG.debug("topic {} doesn't have write credentials", topic);
@@ -439,7 +439,7 @@ class ProtocolProcessor implements EventHandler<ValueEvent> {
LOG.debug("Session for clientId {} is {}", clientId, session);
String user = (String) session.getAttribute(NettyChannel.ATTR_KEY_USERNAME);
if (!m_authorizator.canRead(topic, user)) {
if (!m_authorizator.canRead(topic, user, clientId)) {
LOG.debug("topic {} doesn't have read credentials", topic);
return;
}
@@ -29,7 +29,7 @@ public class Authorization {
* */
enum Permission {
READ, WRITE, READWRITE
};
}
Authorization(String topic) {
this(topic, Permission.READWRITE);
@@ -42,6 +42,7 @@ class AuthorizationsCollector implements IAuthorizator {
private List<Authorization> m_patternAuthorizations = new ArrayList();
private Map<String, List<Authorization>> m_userAuthorizations = new HashMap();
private boolean m_parsingUsersSpecificSection = false;
private boolean m_parsingPatternSpecificSection = false;
private String m_currentUser = "";
static final AuthorizationsCollector emptyImmutableCollector() {
@@ -65,6 +66,8 @@ class AuthorizationsCollector implements IAuthorizator {
}
List<Authorization> userAuths = m_userAuthorizations.get(m_currentUser);
userAuths.add(acl);
} else if (m_parsingPatternSpecificSection) {
m_patternAuthorizations.add(acl);
} else {
m_globalAuthorizations.add(acl);
}
@@ -75,43 +78,50 @@ class AuthorizationsCollector implements IAuthorizator {
String keyword = tokens[0].toLowerCase();
switch (keyword) {
case "topic":
if (tokens.length > 2) {
//if the tokenized lines has 3 token the second must be the permission
try {
Authorization.Permission permission = Authorization.Permission.valueOf(tokens[1].toUpperCase());
//bring topic with all original spacing
String topic = line.substring(line.indexOf(tokens[2]));
return new Authorization(topic, permission);
} catch (IllegalArgumentException iaex) {
throw new ParseException("invalid permission token", 1);
}
}
String topic = tokens[1];
return new Authorization(topic);
return createAuthorization(line, tokens);
case "user":
m_parsingUsersSpecificSection = true;
m_currentUser = tokens[1];
m_parsingPatternSpecificSection = false;
return null;
case "pattern":
//TODO implement the part for patter matching
return null;
m_parsingUsersSpecificSection = false;
m_currentUser = "";
m_parsingPatternSpecificSection = true;
return createAuthorization(line, tokens);
default:
throw new ParseException(String.format("invalid line definition found %s", line), 1);
}
}
@Override
public boolean canWrite(String topic, String user) {
return canDoOperation(topic, WRITE, user);
private Authorization createAuthorization(String line, String[] tokens) throws ParseException {
if (tokens.length > 2) {
//if the tokenized lines has 3 token the second must be the permission
try {
Authorization.Permission permission = Authorization.Permission.valueOf(tokens[1].toUpperCase());
//bring topic with all original spacing
String topic = line.substring(line.indexOf(tokens[2]));
return new Authorization(topic, permission);
} catch (IllegalArgumentException iaex) {
throw new ParseException("invalid permission token", 1);
}
}
String topic = tokens[1];
return new Authorization(topic);
}
@Override
public boolean canRead(String topic, String user) {
return canDoOperation(topic, READ, user);
public boolean canWrite(String topic, String user, String client) {
return canDoOperation(topic, WRITE, user, client);
}
private boolean canDoOperation(String topic, Authorization.Permission permission, String username) {
@Override
public boolean canRead(String topic, String user, String client) {
return canDoOperation(topic, READ, user, client);
}
private boolean canDoOperation(String topic, Authorization.Permission permission, String username, String client) {
for (Authorization auth : m_globalAuthorizations) {
if (auth.permission == permission || auth.permission == READWRITE) {
if (SubscriptionsStore.matchTopics(topic, auth.topic)) {
@@ -120,6 +130,17 @@ class AuthorizationsCollector implements IAuthorizator {
}
}
if (client != null && !client.isEmpty()) {
for (Authorization auth : m_patternAuthorizations) {
String substitutedTopic = auth.topic.replace("%c", client);
if (auth.permission == permission || auth.permission == READWRITE) {
if (SubscriptionsStore.matchTopics(topic, substitutedTopic)) {
return true;
}
}
}
}
if (username != null && !username.isEmpty()) {
if (m_userAuthorizations.containsKey(username)) {
for (Authorization auth : m_userAuthorizations.get(username)) {
@@ -20,12 +20,12 @@ package org.eclipse.moquette.spi.impl.security;
*/
public class DenyAllAuthorizator implements IAuthorizator {
@Override
public boolean canWrite(String topic, String user) {
public boolean canWrite(String topic, String user, String client) {
return true;
}
@Override
public boolean canRead(String topic, String user) {
public boolean canRead(String topic, String user, String client) {
return true;
}
}
@@ -29,7 +29,7 @@ public interface IAuthorizator {
/**
* Ask the implementation of the authorizator if the topic can be used in a publish.
* */
boolean canWrite(String topic, String user);
boolean canWrite(String topic, String user, String client);
boolean canRead(String topic, String user);
boolean canRead(String topic, String user, String client);
}
@@ -20,12 +20,12 @@ package org.eclipse.moquette.spi.impl.security;
*/
public class PermitAllAuthorizator implements IAuthorizator {
@Override
public boolean canWrite(String topic, String user) {
public boolean canWrite(String topic, String user, String client) {
return true;
}
@Override
public boolean canRead(String topic, String user) {
public boolean canRead(String topic, String user, String client) {
return true;
}
}