diff options
Diffstat (limited to 'java/broker-plugins')
54 files changed, 2565 insertions, 764 deletions
diff --git a/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/PlainConfiguration.java b/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/PlainConfiguration.java index 9a08eb6499..afaece6138 100644 --- a/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/PlainConfiguration.java +++ b/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/PlainConfiguration.java @@ -1,5 +1,5 @@ /* - * + * * 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 @@ -7,16 +7,16 @@ * 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.config; @@ -44,43 +44,41 @@ public class PlainConfiguration extends AbstractConfiguration public static final Character COMMENT = '#'; public static final Character CONTINUATION = '\\'; - public static final String GROUP = "group"; public static final String ACL = "acl"; public static final String CONFIG = "config"; public static final String UNRECOGNISED_INITIAL_MSG = "Unrecognised initial token '%s' at line %d"; public static final String NOT_ENOUGH_TOKENS_MSG = "Not enough tokens at line %d"; - public static final String NUMBER_NOT_ALLOWED_MSG = "Number not allowed before '%s' at line %d"; + public static final String NUMBER_NOT_ALLOWED_MSG = "Number not allowed before '%s' at line %d"; public static final String CANNOT_LOAD_MSG = "Cannot load config file %s"; public static final String PREMATURE_CONTINUATION_MSG = "Premature continuation character at line %d"; public static final String PREMATURE_EOF_MSG = "Premature end of file reached at line %d"; public static final String PARSE_TOKEN_FAILED_MSG = "Failed to parse token at line %d"; public static final String CONFIG_NOT_FOUND_MSG = "Cannot find config file %s"; - public static final String NOT_ENOUGH_GROUP_MSG = "Not enough data for a group at line %d"; public static final String NOT_ENOUGH_ACL_MSG = "Not enough data for an acl at line %d"; public static final String NOT_ENOUGH_CONFIG_MSG = "Not enough data for config at line %d"; public static final String BAD_ACL_RULE_NUMBER_MSG = "Invalid rule number at line %d"; public static final String PROPERTY_KEY_ONLY_MSG = "Incomplete property (key only) at line %d"; public static final String PROPERTY_NO_EQUALS_MSG = "Incomplete property (no equals) at line %d"; public static final String PROPERTY_NO_VALUE_MSG = "Incomplete property (no value) at line %d"; - + private StreamTokenizer _st; public PlainConfiguration(File file) { super(file); } - + @Override public RuleSet load() throws ConfigurationException { RuleSet ruleSet = super.load(); - + try { _st = new StreamTokenizer(new BufferedReader(new FileReader(getFile()))); _st.resetSyntax(); // setup the tokenizer - + _st.commentChar(COMMENT); // single line comments _st.eolIsSignificant(true); // return EOL as a token _st.ordinaryChar('='); // equals is a token @@ -97,7 +95,7 @@ public class PlainConfiguration extends AbstractConfiguration _st.wordChars('*', '*'); // star _st.wordChars('@', '@'); // at _st.wordChars(':', ':'); // colon - + // parse the acl file lines Stack<String> stack = new Stack<String>(); int current; @@ -111,7 +109,7 @@ public class PlainConfiguration extends AbstractConfiguration { break; // blank line } - + // pull out the first token from the bottom of the stack and check arguments exist String first = stack.firstElement(); stack.removeElementAt(0); @@ -119,13 +117,13 @@ public class PlainConfiguration extends AbstractConfiguration { throw new ConfigurationException(String.format(NOT_ENOUGH_TOKENS_MSG, getLine())); } - + // check for and parse optional initial number for ACL lines Integer number = null; if (StringUtils.isNumeric(first)) { // set the acl number and get the next element - number = Integer.valueOf(first); + number = Integer.valueOf(first); first = stack.firstElement(); stack.removeElementAt(0); } @@ -136,9 +134,9 @@ public class PlainConfiguration extends AbstractConfiguration } else if (number == null) { - if (StringUtils.equalsIgnoreCase(GROUP, first)) + if(StringUtils.equalsIgnoreCase("GROUP", first)) { - parseGroup(stack); + throw new ConfigurationException(String.format("GROUP keyword not supported. Groups should defined via a Group Provider, not in the ACL file.", getLine())); } else if (StringUtils.equalsIgnoreCase(CONFIG, first)) { @@ -153,7 +151,7 @@ public class PlainConfiguration extends AbstractConfiguration { throw new ConfigurationException(String.format(NUMBER_NOT_ALLOWED_MSG, first, getLine())); } - + // reset stack, start next line stack.clear(); break; @@ -171,7 +169,7 @@ public class PlainConfiguration extends AbstractConfiguration { break; // continue reading next line } - + // invalid location for continuation character (add one to line beacuse we ate the EOL) throw new ConfigurationException(String.format(PREMATURE_CONTINUATION_MSG, getLine() + 1)); } @@ -185,7 +183,7 @@ public class PlainConfiguration extends AbstractConfiguration } } } while (current != StreamTokenizer.TT_EOF); - + if (!stack.isEmpty()) { throw new ConfigurationException(String.format(PREMATURE_EOF_MSG, getLine())); @@ -203,20 +201,10 @@ public class PlainConfiguration extends AbstractConfiguration { throw new ConfigurationException(String.format(CANNOT_LOAD_MSG, getFile().getName()), ioe); } - + return ruleSet; } - - private void parseGroup(List<String> args) throws ConfigurationException - { - if (args.size() < 2) - { - throw new ConfigurationException(String.format(NOT_ENOUGH_GROUP_MSG, getLine())); - } - - getConfiguration().addGroup(args.get(0), args.subList(1, args.size())); - } - + private void parseAcl(Integer number, List<String> args) throws ConfigurationException { if (args.size() < 3) @@ -227,12 +215,12 @@ public class PlainConfiguration extends AbstractConfiguration Permission permission = Permission.parse(args.get(0)); String identity = args.get(1); Operation operation = Operation.parse(args.get(2)); - + if (number != null && !getConfiguration().isValidNumber(number)) { throw new ConfigurationException(String.format(BAD_ACL_RULE_NUMBER_MSG, getLine())); } - + if (args.size() == 3) { getConfiguration().grant(number, identity, permission, operation); @@ -245,7 +233,7 @@ public class PlainConfiguration extends AbstractConfiguration getConfiguration().grant(number, identity, permission, operation, object, properties); } } - + private void parseConfig(List<String> args) throws ConfigurationException { if (args.size() < 3) @@ -254,10 +242,10 @@ public class PlainConfiguration extends AbstractConfiguration } Map<String, Boolean> properties = toPluginProperties(args); - + getConfiguration().configure(properties); } - + /** Converts a {@link List} of "name", "=", "value" tokens into a {@link Map}. */ protected ObjectProperties toObjectProperties(List<String> args) throws ConfigurationException { @@ -279,14 +267,14 @@ public class PlainConfiguration extends AbstractConfiguration throw new ConfigurationException(String.format(PROPERTY_NO_VALUE_MSG, getLine())); } String value = i.next(); - + // parse property key ObjectProperties.Property property = ObjectProperties.Property.parse(key); properties.put(property, value); } return properties; } - + /** Converts a {@link List} of "name", "=", "value" tokens into a {@link Map}. */ protected Map<String, Boolean> toPluginProperties(List<String> args) throws ConfigurationException { @@ -307,14 +295,14 @@ public class PlainConfiguration extends AbstractConfiguration { throw new ConfigurationException(String.format(PROPERTY_NO_VALUE_MSG, getLine())); } - + // parse property value and save Boolean value = Boolean.valueOf(i.next()); properties.put(key, value); } return properties; } - + protected int getLine() { return _st.lineno() - 1; diff --git a/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/Rule.java b/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/Rule.java index 15d6b67192..5e98e0bd1b 100644 --- a/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/Rule.java +++ b/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/Rule.java @@ -29,7 +29,7 @@ import org.apache.qpid.server.security.access.Permission; /** * An access control v2 rule. - * + * * A rule consists of {@link Permission} for a particular identity to perform an {@link Action}. The identity * may be either a user or a group. */ @@ -37,13 +37,13 @@ public class Rule implements Comparable<Rule> { /** String indicating all identitied. */ public static final String ALL = "all"; - + private Integer _number; private Boolean _enabled = Boolean.TRUE; private String _identity; private Action _action; private Permission _permission; - + public Rule(Integer number, String identity, Action action, Permission permission) { setNumber(number); @@ -51,27 +51,27 @@ public class Rule implements Comparable<Rule> setAction(action); setPermission(permission); } - + public Rule(String identity, Action action, Permission permission) { this(null, identity, action, permission); } - + public boolean isEnabled() { return _enabled; } - + public void setEnabled(boolean enabled) { _enabled = enabled; } - + public void enable() { _enabled = Boolean.TRUE; } - + public void disable() { _enabled = Boolean.FALSE; @@ -96,7 +96,7 @@ public class Rule implements Comparable<Rule> { _identity = identity; } - + public Action getAction() { return _action; @@ -136,7 +136,7 @@ public class Rule implements Comparable<Rule> return false; } Rule r = (Rule) o; - + return new EqualsBuilder() .append(getIdentity(), r.getIdentity()) .append(getAction(), r.getAction()) diff --git a/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/RuleSet.java b/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/RuleSet.java index 815df99f80..2477455de4 100644 --- a/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/RuleSet.java +++ b/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/RuleSet.java @@ -19,7 +19,6 @@ package org.apache.qpid.server.security.access.config; import java.security.Principal; -import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.EnumMap; @@ -66,7 +65,6 @@ public class RuleSet private static final Integer _increment = 10; - private final Map<String, List<String>> _aclGroups = new HashMap<String, List<String>>(); private final SortedMap<Integer, Rule> _rules = new TreeMap<Integer, Rule>(); private final Map<Subject, Map<Operation, Map<ObjectType, List<Rule>>>> _cache = new WeakHashMap<Subject, Map<Operation, Map<ObjectType, List<Rule>>>>(); @@ -79,14 +77,13 @@ public class RuleSet } /** - * Clear the contents, including acl groups, rules and configuration. + * Clear the contents, including acl rules and configuration. */ public void clear() { _rules.clear(); _cache.clear(); _config.clear(); - _aclGroups.clear(); } public int getRuleCount() @@ -222,53 +219,6 @@ public class RuleSet _rules.get(Integer.valueOf(ruleNumber)).disable(); } - public boolean addGroup(String group, List<String> constituents) - { - _cache.clear(); - - if (_aclGroups.containsKey(group)) - { - // cannot redefine - return false; - } - else - { - _aclGroups.put(group, new ArrayList<String>()); - } - - for (String name : constituents) - { - if (name.equalsIgnoreCase(group)) - { - // recursive definition - return false; - } - - if (!checkName(name)) - { - // invalid name - return false; - } - - if (_aclGroups.containsKey(name)) - { - // is a group - _aclGroups.get(group).addAll(_aclGroups.get(name)); - } - else - { - // is a user - if (!isvalidUserName(name)) - { - // invalid username - return false; - } - _aclGroups.get(group).add(name); - } - } - return true; - } - /** Return true if the name is well-formed (contains legal characters). */ protected boolean checkName(String name) { @@ -312,12 +262,6 @@ public class RuleSet return true; } - // CPP broker authorise function prototype - // virtual bool authorise(const std::string& id, const Action& action, const ObjectType& objType, - // const std::string& name, std::map<Property, std::string>* params=0) - - // Possibly add a String name paramater? - /** * Check the authorisation granted to a particular identity for an operation on an object type with * specific properties. @@ -446,8 +390,7 @@ public class RuleSet { final Principal principal = iterator.next(); - if (rule.getIdentity().equalsIgnoreCase(principal.getName()) - || (_aclGroups.containsKey(rule.getIdentity()) && _aclGroups.get(rule.getIdentity()).contains(principal.getName()))) + if (rule.getIdentity().equalsIgnoreCase(principal.getName())) { return true; } diff --git a/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/AccessControl.java b/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/AccessControl.java index d8a5bd4085..d36ae810c6 100644 --- a/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/AccessControl.java +++ b/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/AccessControl.java @@ -40,9 +40,9 @@ import org.apache.qpid.server.security.access.config.RuleSet; public class AccessControl extends AbstractPlugin { public static final Logger _logger = Logger.getLogger(AccessControl.class); - + private RuleSet _ruleSet; - + public static final SecurityPluginFactory<AccessControl> FACTORY = new SecurityPluginFactory<AccessControl>() { public Class<AccessControl> getPluginClass() @@ -86,7 +86,7 @@ public class AccessControl extends AbstractPlugin { return authorise(Operation.ACCESS, objectType, ObjectProperties.EMPTY); } - + /** * Check if an operation is authorised by asking the configuration object about the access * control rules granted to the current thread's {@link Subject}. If there is no current @@ -100,7 +100,7 @@ public class AccessControl extends AbstractPlugin { return Result.ABSTAIN; } - + _logger.debug("Checking " + operation + " " + objectType); return _ruleSet.check(subject, operation, objectType, properties); } diff --git a/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/AccessControlConfiguration.java b/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/AccessControlConfiguration.java index c4db6db820..63f7e254ae 100644 --- a/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/AccessControlConfiguration.java +++ b/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/AccessControlConfiguration.java @@ -34,7 +34,7 @@ import org.apache.qpid.server.security.access.config.RuleSet; public class AccessControlConfiguration extends ConfigurationPlugin { - public static final ConfigurationPluginFactory FACTORY = new ConfigurationPluginFactory() + public static final ConfigurationPluginFactory FACTORY = new ConfigurationPluginFactory() { public ConfigurationPlugin newInstance(String path, Configuration config) throws ConfigurationException { @@ -70,7 +70,7 @@ public class AccessControlConfiguration extends ConfigurationPlugin } File aclFile = new File(filename); - + ConfigurationFile configFile = new PlainConfiguration(aclFile); _ruleSet = configFile.load(); } diff --git a/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/AccessControlTest.java b/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/AccessControlTest.java index 5db02d10ce..2385bcc3dd 100644 --- a/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/AccessControlTest.java +++ b/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/AccessControlTest.java @@ -20,8 +20,6 @@ */ package org.apache.qpid.server.security.access.plugins; -import java.util.Arrays; - import junit.framework.TestCase; import org.apache.commons.configuration.ConfigurationException; @@ -37,19 +35,22 @@ import org.apache.qpid.server.security.access.Operation; import org.apache.qpid.server.security.access.Permission; import org.apache.qpid.server.security.access.config.Rule; import org.apache.qpid.server.security.access.config.RuleSet; -import org.apache.qpid.server.security.auth.sasl.TestPrincipalUtils; +import org.apache.qpid.server.security.auth.TestPrincipalUtils; /** - * Unit test for ACL V2 plugin. - * + * Unit test for ACL V2 plugin. + * * This unit test tests the AccessControl class and it collaboration with {@link RuleSet}, * {@link SecurityManager} and {@link CurrentActor}. The ruleset is configured programmatically, * rather than from an external file. - * + * * @see RuleSetTest */ public class AccessControlTest extends TestCase { + private static final String ALLOWED_GROUP = "allowed_group"; + private static final String DENIED_GROUP = "denied_group"; + private AccessControl _plugin = null; // Class under test private final UnitTestMessageLogger messageLogger = new UnitTestMessageLogger(); @@ -68,14 +69,12 @@ public class AccessControlTest extends TestCase private RuleSet createGroupRuleSet() { final RuleSet rs = new RuleSet(); - rs.addGroup("aclGroup1", Arrays.asList(new String[] {"member1", "Member2"})); // Rule expressed with username rs.grant(0, "user1", Permission.ALLOW, Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY); - // Rule expressed with a acl group - rs.grant(1, "aclGroup1", Permission.ALLOW, Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY); - // Rule expressed with an external group - rs.grant(2, "extGroup1", Permission.DENY, Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY); + // Rules expressed with groups + rs.grant(1, ALLOWED_GROUP, Permission.ALLOW, Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY); + rs.grant(2, DENIED_GROUP, Permission.DENY, Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY); // Catch all rule rs.grant(3, Rule.ALL, Permission.DENY_LOG, Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY); @@ -117,31 +116,23 @@ public class AccessControlTest extends TestCase * Tests that an allow rule expressed with an <b>ACL groupname</b> allows an operation performed by a thread running * by a user who belongs to the same group.. */ - public void testAclGroupMembershipAllowsOperation() throws ConfigurationException + public void testGroupMembershipAllowsOperation() throws ConfigurationException { setUpGroupAccessControl(); - SecurityManager.setThreadSubject(TestPrincipalUtils.createTestSubject("member1")); - Result result = _plugin.authorise(Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY); - assertEquals(Result.ALLOWED, result); - - SecurityManager.setThreadSubject(TestPrincipalUtils.createTestSubject("Member2")); - - result = _plugin.authorise(Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY); - assertEquals(Result.ALLOWED, result); + authoriseAndAssertResult(Result.ALLOWED, "member of allowed group", ALLOWED_GROUP); + authoriseAndAssertResult(Result.DENIED, "member of denied group", DENIED_GROUP); + authoriseAndAssertResult(Result.ALLOWED, "another member of allowed group", ALLOWED_GROUP); } /** - * Tests that a deny rule expressed with an <b>External groupname</b> denies an operation performed by a thread running + * Tests that a deny rule expressed with a <b>groupname</b> denies an operation performed by a thread running * by a user who belongs to the same group. */ - public void testExternalGroupMembershipDeniesOperation() throws ConfigurationException + public void testGroupMembershipDeniesOperation() throws ConfigurationException { setUpGroupAccessControl(); - SecurityManager.setThreadSubject(TestPrincipalUtils.createTestSubject("user3", "extGroup1")); - - final Result result = _plugin.authorise(Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY); - assertEquals(Result.DENIED, result); + authoriseAndAssertResult(Result.DENIED, "user3", DENIED_GROUP); } /** @@ -325,6 +316,14 @@ public class AccessControlTest extends TestCase assertEquals(Result.DEFER, result); } + private void authoriseAndAssertResult(Result expectedResult, String userName, String... groups) + { + SecurityManager.setThreadSubject(TestPrincipalUtils.createTestSubject(userName, groups)); + + Result result = _plugin.authorise(Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY); + assertEquals(expectedResult, result); + } + /** * Creates a configuration plugin for the {@link AccessControl} plugin. */ diff --git a/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/PlainConfigurationTest.java b/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/PlainConfigurationTest.java index c2282694fb..be4962615c 100644 --- a/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/PlainConfigurationTest.java +++ b/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/PlainConfigurationTest.java @@ -108,19 +108,6 @@ public class PlainConfigurationTest extends TestCase } } - public void testACLFileSyntaxNotEnoughGroup() throws Exception - { - try - { - writeACLConfig("GROUP blah"); - fail("fail"); - } - catch (ConfigurationException ce) - { - assertEquals(String.format(PlainConfiguration.NOT_ENOUGH_GROUP_MSG, 1), ce.getMessage()); - } - } - public void testACLFileSyntaxNotEnoughACL() throws Exception { try @@ -391,4 +378,77 @@ public class PlainConfigurationTest extends TestCase assertEquals("Rule has unexpected object properties", ObjectProperties.EMPTY, rule.getAction().getProperties()); } + public void testUserRuleParsing() throws Exception + { + validateRule(writeACLConfig("ACL ALLOW user1 CREATE USER"), + "user1", Operation.CREATE, ObjectType.USER, ObjectProperties.EMPTY); + validateRule(writeACLConfig("ACL ALLOW user1 CREATE USER name=\"otherUser\""), + "user1", Operation.CREATE, ObjectType.USER, new ObjectProperties("otherUser")); + + validateRule(writeACLConfig("ACL ALLOW user1 DELETE USER"), + "user1", Operation.DELETE, ObjectType.USER, ObjectProperties.EMPTY); + validateRule(writeACLConfig("ACL ALLOW user1 DELETE USER name=\"otherUser\""), + "user1", Operation.DELETE, ObjectType.USER, new ObjectProperties("otherUser")); + + validateRule(writeACLConfig("ACL ALLOW user1 UPDATE USER"), + "user1", Operation.UPDATE, ObjectType.USER, ObjectProperties.EMPTY); + validateRule(writeACLConfig("ACL ALLOW user1 UPDATE USER name=\"otherUser\""), + "user1", Operation.UPDATE, ObjectType.USER, new ObjectProperties("otherUser")); + + validateRule(writeACLConfig("ACL ALLOW user1 ALL USER"), + "user1", Operation.ALL, ObjectType.USER, ObjectProperties.EMPTY); + validateRule(writeACLConfig("ACL ALLOW user1 ALL USER name=\"otherUser\""), + "user1", Operation.ALL, ObjectType.USER, new ObjectProperties("otherUser")); + } + + public void testGroupRuleParsing() throws Exception + { + validateRule(writeACLConfig("ACL ALLOW user1 CREATE GROUP"), + "user1", Operation.CREATE, ObjectType.GROUP, ObjectProperties.EMPTY); + validateRule(writeACLConfig("ACL ALLOW user1 CREATE GROUP name=\"groupName\""), + "user1", Operation.CREATE, ObjectType.GROUP, new ObjectProperties("groupName")); + + validateRule(writeACLConfig("ACL ALLOW user1 DELETE GROUP"), + "user1", Operation.DELETE, ObjectType.GROUP, ObjectProperties.EMPTY); + validateRule(writeACLConfig("ACL ALLOW user1 DELETE GROUP name=\"groupName\""), + "user1", Operation.DELETE, ObjectType.GROUP, new ObjectProperties("groupName")); + + validateRule(writeACLConfig("ACL ALLOW user1 UPDATE GROUP"), + "user1", Operation.UPDATE, ObjectType.GROUP, ObjectProperties.EMPTY); + validateRule(writeACLConfig("ACL ALLOW user1 UPDATE GROUP name=\"groupName\""), + "user1", Operation.UPDATE, ObjectType.GROUP, new ObjectProperties("groupName")); + + validateRule(writeACLConfig("ACL ALLOW user1 ALL GROUP"), + "user1", Operation.ALL, ObjectType.GROUP, ObjectProperties.EMPTY); + validateRule(writeACLConfig("ACL ALLOW user1 ALL GROUP name=\"groupName\""), + "user1", Operation.ALL, ObjectType.GROUP, new ObjectProperties("groupName")); + } + + /** explicitly test for exception indicating that this functionality has been moved to Group Providers */ + public void testGroupDefinitionThrowsException() throws Exception + { + try + { + writeACLConfig("GROUP group1 bob alice"); + fail("Expected exception not thrown"); + } + catch(ConfigurationException e) + { + assertTrue(e.getMessage().contains("GROUP keyword not supported")); + } + } + + private void validateRule(final PlainConfiguration config, String username, Operation operation, ObjectType objectType, ObjectProperties objectProperties) + { + final RuleSet rs = config.getConfiguration(); + assertEquals(1, rs.getRuleCount()); + + final Map<Integer, Rule> rules = rs.getAllRules(); + assertEquals(1, rules.size()); + final Rule rule = rules.get(0); + assertEquals("Rule has unexpected identity", username, rule.getIdentity()); + assertEquals("Rule has unexpected operation", operation, rule.getAction().getOperation()); + assertEquals("Rule has unexpected operation", objectType, rule.getAction().getObjectType()); + assertEquals("Rule has unexpected object properties", objectProperties, rule.getAction().getProperties()); + } } diff --git a/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/RuleSetTest.java b/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/RuleSetTest.java index f7cc60543d..181d693614 100644 --- a/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/RuleSetTest.java +++ b/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/RuleSetTest.java @@ -22,7 +22,6 @@ package org.apache.qpid.server.security.access.plugins; import java.security.Principal; -import java.util.Arrays; import javax.security.auth.Subject; @@ -34,8 +33,7 @@ import org.apache.qpid.server.security.access.Operation; import org.apache.qpid.server.security.access.Permission; import org.apache.qpid.server.security.access.config.Rule; import org.apache.qpid.server.security.access.config.RuleSet; -import org.apache.qpid.server.security.auth.sasl.TestPrincipalUtils; -import org.apache.qpid.server.security.auth.sasl.UsernamePrincipal; +import org.apache.qpid.server.security.auth.TestPrincipalUtils; import org.apache.qpid.test.utils.QpidTestCase; /** @@ -46,10 +44,7 @@ import org.apache.qpid.test.utils.QpidTestCase; * access control mechanism is validated by checking whether operations would be authorised by calling the * {@link RuleSet#check(Principal, Operation, ObjectType, ObjectProperties)} method. * - * It ensure that permissions can be granted correctly on users directly, ACL groups (that is those - * groups declared directly in the ACL itself), and External groups (that is a group from an External - * Authentication Provider, such as an LDAP). - + * It ensure that permissions can be granted correctly on users directly and on groups. */ public class RuleSetTest extends QpidTestCase { @@ -316,63 +311,36 @@ public class RuleSetTest extends QpidTestCase assertEquals(Result.ALLOWED, _ruleSet.check(TestPrincipalUtils.createTestSubject("userb"),Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY)); } - /** - * Tests support for ACL groups (i.e. inline groups declared in the ACL file itself). - */ - public void testAclGroupsSupported() + public void testGroupsSupported() { - assertTrue(_ruleSet.addGroup("aclgroup", Arrays.asList(new String[] {"usera", "userb"}))); - - _ruleSet.grant(1, "aclgroup", Permission.ALLOW, Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY); - assertEquals(1, _ruleSet.getRuleCount()); - - assertEquals(Result.ALLOWED, _ruleSet.check(TestPrincipalUtils.createTestSubject("usera"),Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY)); - assertEquals(Result.ALLOWED, _ruleSet.check(TestPrincipalUtils.createTestSubject("userb"),Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY)); - assertEquals(Result.DEFER, _ruleSet.check(TestPrincipalUtils.createTestSubject("userc"),Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY)); - } - - /** - * Tests support for nested ACL groups. - */ - public void testNestedAclGroupsSupported() - { - assertTrue(_ruleSet.addGroup("aclgroup1", Arrays.asList(new String[] {"userb"}))); - assertTrue(_ruleSet.addGroup("aclgroup2", Arrays.asList(new String[] {"usera", "aclgroup1"}))); - - _ruleSet.grant(1, "aclgroup2", Permission.ALLOW, Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY); - assertEquals(1, _ruleSet.getRuleCount()); + String allowGroup = "allowGroup"; + String deniedGroup = "deniedGroup"; - assertEquals(Result.ALLOWED, _ruleSet.check(TestPrincipalUtils.createTestSubject("usera"),Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY)); - assertEquals(Result.ALLOWED, _ruleSet.check(TestPrincipalUtils.createTestSubject("userb"),Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY)); - } + _ruleSet.grant(1, allowGroup, Permission.ALLOW, Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY); + _ruleSet.grant(2, deniedGroup, Permission.DENY, Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY); - /** - * Tests support for nested External groups (i.e. those groups coming from an external source such as an LDAP). - */ - public void testExternalGroupsSupported() - { - _ruleSet.grant(1, "extgroup1", Permission.ALLOW, Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY); - _ruleSet.grant(2, "extgroup2", Permission.DENY, Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY); assertEquals(2, _ruleSet.getRuleCount()); - assertEquals(Result.ALLOWED, _ruleSet.check(TestPrincipalUtils.createTestSubject("usera", "extgroup1"),Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY)); - assertEquals(Result.DENIED, _ruleSet.check(TestPrincipalUtils.createTestSubject("userb", "extgroup2"),Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY)); + assertEquals(Result.ALLOWED, _ruleSet.check(TestPrincipalUtils.createTestSubject("usera", allowGroup),Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY)); + assertEquals(Result.DENIED, _ruleSet.check(TestPrincipalUtils.createTestSubject("userb", deniedGroup),Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY)); + assertEquals(Result.DEFER, _ruleSet.check(TestPrincipalUtils.createTestSubject("user", "group not mentioned in acl"),Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY)); } /** * Rule order in the ACL determines the outcome of the check. This test ensures that a user who is - * granted explicit permission on an object, is granted that access even although late a group + * granted explicit permission on an object, is granted that access even though a group * to which the user belongs is later denied the permission. */ public void testAllowDeterminedByRuleOrder() { - assertTrue(_ruleSet.addGroup("aclgroup", Arrays.asList(new String[] {"usera"}))); + String group = "group"; + String user = "user"; - _ruleSet.grant(1, "usera", Permission.ALLOW, Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY); - _ruleSet.grant(2, "aclgroup", Permission.DENY, Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY); + _ruleSet.grant(1, user, Permission.ALLOW, Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY); + _ruleSet.grant(2, group, Permission.DENY, Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY); assertEquals(2, _ruleSet.getRuleCount()); - assertEquals(Result.ALLOWED, _ruleSet.check(TestPrincipalUtils.createTestSubject("usera"),Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY)); + assertEquals(Result.ALLOWED, _ruleSet.check(TestPrincipalUtils.createTestSubject(user, group),Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY)); } /** @@ -381,13 +349,33 @@ public class RuleSetTest extends QpidTestCase */ public void testDenyDeterminedByRuleOrder() { - assertTrue(_ruleSet.addGroup("aclgroup", Arrays.asList(new String[] {"usera"}))); + String group = "aclgroup"; + String user = "usera"; - _ruleSet.grant(1, "aclgroup", Permission.DENY, Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY); - _ruleSet.grant(2, "usera", Permission.ALLOW, Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY); + _ruleSet.grant(1, group, Permission.DENY, Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY); + _ruleSet.grant(2, user, Permission.ALLOW, Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY); assertEquals(2, _ruleSet.getRuleCount()); - assertEquals(Result.DENIED, _ruleSet.check(TestPrincipalUtils.createTestSubject("usera"),Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY)); + assertEquals(Result.DENIED, _ruleSet.check(TestPrincipalUtils.createTestSubject(user, group),Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY)); + } + + public void testUserInMultipleGroups() + { + String allowedGroup = "group1"; + String deniedGroup = "group2"; + + _ruleSet.grant(1, allowedGroup, Permission.ALLOW, Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY); + _ruleSet.grant(2, deniedGroup, Permission.DENY, Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY); + + Subject subjectInBothGroups = TestPrincipalUtils.createTestSubject("user", allowedGroup, deniedGroup); + Subject subjectInDeniedGroupAndOneOther = TestPrincipalUtils.createTestSubject("user", deniedGroup, "some other group"); + Subject subjectInAllowedGroupAndOneOther = TestPrincipalUtils.createTestSubject("user", allowedGroup, "some other group"); + + assertEquals(Result.ALLOWED, _ruleSet.check(subjectInBothGroups,Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY)); + + assertEquals(Result.DENIED, _ruleSet.check(subjectInDeniedGroupAndOneOther,Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY)); + + assertEquals(Result.ALLOWED, _ruleSet.check(subjectInAllowedGroupAndOneOther,Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY)); } } diff --git a/java/broker-plugins/management-http/MANIFEST.MF b/java/broker-plugins/management-http/MANIFEST.MF index cca10d3f89..525801f65f 100644 --- a/java/broker-plugins/management-http/MANIFEST.MF +++ b/java/broker-plugins/management-http/MANIFEST.MF @@ -20,6 +20,7 @@ Import-Package: org.apache.qpid, org.apache.qpid.server.binding, org.apache.qpid.server.exchange, org.apache.qpid.server.logging, + org.apache.qpid.server.logging.actors, org.apache.qpid.server.message, org.apache.qpid.server.model, org.apache.qpid.server.model.adapter, diff --git a/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/Management.java b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/Management.java index c2f9b73b54..38a8722852 100644 --- a/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/Management.java +++ b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/Management.java @@ -44,6 +44,9 @@ import org.apache.qpid.server.model.Broker; import org.apache.qpid.server.model.ConfiguredObject; import org.apache.qpid.server.model.Connection; import org.apache.qpid.server.model.Exchange; +import org.apache.qpid.server.model.Group; +import org.apache.qpid.server.model.GroupMember; +import org.apache.qpid.server.model.GroupProvider; import org.apache.qpid.server.model.Port; import org.apache.qpid.server.model.Protocol; import org.apache.qpid.server.model.Queue; @@ -158,6 +161,9 @@ public class Management addRestServlet(root, "virtualhost", VirtualHost.class); addRestServlet(root, "authenticationprovider", AuthenticationProvider.class); addRestServlet(root, "user", AuthenticationProvider.class, User.class); + addRestServlet(root, "groupprovider", GroupProvider.class); + addRestServlet(root, "group", GroupProvider.class, Group.class); + addRestServlet(root, "groupmember", GroupProvider.class, Group.class, GroupMember.class); addRestServlet(root, "exchange", VirtualHost.class, Exchange.class); addRestServlet(root, "queue", VirtualHost.class, Queue.class); addRestServlet(root, "connection", VirtualHost.class, Connection.class); diff --git a/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/AbstractServlet.java b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/AbstractServlet.java index a76bd98179..1469808565 100644 --- a/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/AbstractServlet.java +++ b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/AbstractServlet.java @@ -24,8 +24,10 @@ package org.apache.qpid.server.management.plugin.servlet.rest; import java.io.IOException; import java.net.InetSocketAddress; import java.net.SocketAddress; -import java.security.Principal; -import java.util.Collections; +import java.security.AccessControlException; +import java.security.PrivilegedActionException; +import java.security.PrivilegedExceptionAction; + import javax.security.auth.Subject; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; @@ -33,168 +35,293 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import org.apache.commons.codec.binary.Base64; +import org.apache.log4j.Logger; +import org.apache.qpid.server.logging.LogActor; +import org.apache.qpid.server.logging.RootMessageLogger; +import org.apache.qpid.server.logging.actors.CurrentActor; +import org.apache.qpid.server.logging.actors.HttpManagementActor; import org.apache.qpid.server.model.Broker; import org.apache.qpid.server.registry.ApplicationRegistry; -import org.apache.qpid.server.security.auth.AuthenticationResult; +import org.apache.qpid.server.security.SubjectCreator; +import org.apache.qpid.server.security.auth.AuthenticationResult.AuthenticationStatus; +import org.apache.qpid.server.security.auth.SubjectAuthenticationResult; import org.apache.qpid.server.security.auth.manager.AnonymousAuthenticationManager; -import org.apache.qpid.server.security.auth.manager.AuthenticationManager; public abstract class AbstractServlet extends HttpServlet { + private static final Logger LOGGER = Logger.getLogger(AbstractServlet.class); + + protected static final String ATTR_SUBJECT = "subject"; + private static final String ATTR_LOG_ACTOR = "AbstractServlet.logActor"; + private final Broker _broker; + private RootMessageLogger _rootLogger; + protected AbstractServlet() { super(); _broker = ApplicationRegistry.getInstance().getBroker(); + _rootLogger = ApplicationRegistry.getInstance().getRootMessageLogger(); } protected AbstractServlet(Broker broker) { _broker = broker; + _rootLogger = ApplicationRegistry.getInstance().getRootMessageLogger(); } @Override - protected final void doGet(HttpServletRequest request, HttpServletResponse resp) throws ServletException, IOException + protected final void doGet(final HttpServletRequest request, final HttpServletResponse resp) { - setAuthorizedSubject(request); - try - { - onGet(request, resp); - } - finally - { - clearAuthorizedSubject(); - } + doWithSubjectAndActor( + new PrivilegedExceptionAction<Void>() + { + @Override + public Void run() throws Exception + { + doGetWithSubjectAndActor(request, resp); + return null; + } + }, + request, + resp + ); } - protected void onGet(HttpServletRequest request, HttpServletResponse resp) throws IOException, ServletException + /** + * Performs the GET action as the logged-in {@link Subject}. + * The {@link LogActor} is set before this method is called. + * Subclasses commonly override this method + */ + protected void doGetWithSubjectAndActor(HttpServletRequest request, HttpServletResponse resp) throws ServletException, IOException { - super.doGet(request, resp); + throw new UnsupportedOperationException("GET not supported by this servlet"); } - private void clearAuthorizedSubject() + + @Override + protected final void doPost(final HttpServletRequest request, final HttpServletResponse resp) { - org.apache.qpid.server.security.SecurityManager.setThreadSubject(null); + doWithSubjectAndActor( + new PrivilegedExceptionAction<Void>() + { + @Override + public Void run() throws Exception + { + doPostWithSubjectAndActor(request, resp); + return null; + } + }, + request, + resp + ); } - - private void setAuthorizedSubject(HttpServletRequest request) + /** + * Performs the POST action as the logged-in {@link Subject}. + * The {@link LogActor} is set before this method is called. + * Subclasses commonly override this method + */ + protected void doPostWithSubjectAndActor(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { - HttpSession session = request.getSession(true); - Subject subject = (Subject) session.getAttribute("subject"); + throw new UnsupportedOperationException("POST not supported by this servlet"); + } - if(subject == null) - { - Principal principal = request.getUserPrincipal(); - if(principal != null) - { - subject = new Subject(false, Collections.singleton(principal),Collections.emptySet(), - Collections.emptySet()); - } - else + @Override + protected final void doPut(final HttpServletRequest request, final HttpServletResponse resp) + { + doWithSubjectAndActor( + new PrivilegedExceptionAction<Void>() { - String header = request.getHeader("Authorization"); + @Override + public Void run() throws Exception + { + doPutWithSubjectAndActor(request, resp); + return null; + } + }, + request, + resp + ); + } - /* - * TODO - Should configure whether basic authentication is allowed... and in particular whether it - * should be allowed over non-ssl connections - * */ + /** + * Performs the PUT action as the logged-in {@link Subject}. + * The {@link LogActor} is set before this method is called. + * Subclasses commonly override this method + */ + protected void doPutWithSubjectAndActor(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException + { + throw new UnsupportedOperationException("PUT not supported by this servlet"); + } - if (header != null) + @Override + protected final void doDelete(final HttpServletRequest request, final HttpServletResponse resp) + throws ServletException, IOException + { + doWithSubjectAndActor( + new PrivilegedExceptionAction<Void>() + { + @Override + public Void run() throws Exception { - String[] tokens = header.split("\\s"); - if(tokens.length >= 2 - && "BASIC".equalsIgnoreCase(tokens[0])) - { - String[] credentials = (new String(Base64.decodeBase64(tokens[1].getBytes()))).split(":",2); - if(credentials.length == 2) - { - SocketAddress address = getSocketAddress(request); - AuthenticationManager authenticationManager = - ApplicationRegistry.getInstance().getAuthenticationManager(address); - AuthenticationResult authResult = - authenticationManager.authenticate(credentials[0], credentials[1]); - subject = authResult.getSubject(); - - } - } + doDeleteWithSubjectAndActor(request, resp); + return null; } - } - } - if (subject == null) - { - subject = AnonymousAuthenticationManager.ANONYMOUS_SUBJECT; - } - org.apache.qpid.server.security.SecurityManager.setThreadSubject(subject); - + }, + request, + resp + ); } - protected Subject getSubject(HttpSession session) + /** + * Performs the PUT action as the logged-in {@link Subject}. + * The {@link LogActor} is set before this method is called. + * Subclasses commonly override this method + */ + protected void doDeleteWithSubjectAndActor(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { - return (Subject)session.getAttribute("subject"); + throw new UnsupportedOperationException("DELETE not supported by this servlet"); } - @Override - protected final void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException + private void doWithSubjectAndActor( + PrivilegedExceptionAction<Void> privilegedExceptionAction, + final HttpServletRequest request, + final HttpServletResponse resp) { - setAuthorizedSubject(req); + Subject subject = getAndCacheAuthorizedSubject(request); + org.apache.qpid.server.security.SecurityManager.setThreadSubject(subject); + try { - onPost(req, resp); + HttpManagementActor logActor = getLogActorAndCacheInSession(request); + CurrentActor.set(logActor); + try + { + Subject.doAs(subject, privilegedExceptionAction); + } + catch(RuntimeException e) + { + LOGGER.error("Unable to perform action", e); + throw e; + } + catch (PrivilegedActionException e) + { + LOGGER.error("Unable to perform action", e); + throw new RuntimeException(e.getCause()); + } + finally + { + CurrentActor.remove(); + } } finally { - clearAuthorizedSubject(); + org.apache.qpid.server.security.SecurityManager.setThreadSubject(null); } - } - protected void onPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException + /** + * Gets the logged-in {@link Subject} by trying the following: + * + * <ul> + * <li>Get it from the session</li> + * <li>Get it from the request</li> + * <li>Log in using the username and password in the Authorization HTTP header</li> + * <li>Create a Subject representing the anonymous user.</li> + * </ul> + * + * If an authenticated subject is found it is cached in the http session. + */ + private Subject getAndCacheAuthorizedSubject(HttpServletRequest request) { - super.doPost(req, resp); - } + HttpSession session = request.getSession(); + Subject subject = getSubjectFromSession(session); - @Override - protected final void doPut(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException - { - setAuthorizedSubject(req); - try + if(subject != null) { - onPut(req, resp); + return subject; + } + SubjectCreator subjectCreator = ApplicationRegistry.getInstance().getSubjectCreator(getSocketAddress(request)); + + String remoteUser = request.getRemoteUser(); + if(remoteUser != null) + { + subject = subjectCreator.createSubjectWithGroups(remoteUser); } - finally + else { - clearAuthorizedSubject(); + String header = request.getHeader("Authorization"); + + /* + * TODO - Should configure whether basic authentication is allowed... and in particular whether it + * should be allowed over non-ssl connections + * */ + + if (header != null) + { + String[] tokens = header.split("\\s"); + if(tokens.length >= 2 + && "BASIC".equalsIgnoreCase(tokens[0])) + { + String[] credentials = (new String(Base64.decodeBase64(tokens[1].getBytes()))).split(":",2); + if(credentials.length == 2) + { + SubjectAuthenticationResult authResult = subjectCreator.authenticate(credentials[0], credentials[1]); + if( authResult.getStatus() != AuthenticationStatus.SUCCESS) + { + //TODO: write a return response indicating failure? + throw new AccessControlException("Incorrect username or password"); + } + subject = authResult.getSubject(); + } + else + { + //TODO: write a return response indicating failure? + throw new AccessControlException("Invalid number of credentials supplied: " + + credentials.length); + } + } + } } - } - protected void onPut(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException - { - super.doPut(req,resp); + if (subject != null) + { + setSubjectInSession(subject, session); + } + else + { + subject = subjectCreator.createSubjectWithGroups(AnonymousAuthenticationManager.ANONYMOUS_USERNAME); + } + + return subject; } - @Override - protected final void doDelete(HttpServletRequest req, HttpServletResponse resp) - throws ServletException, IOException + private HttpManagementActor getLogActorAndCacheInSession(HttpServletRequest req) { - setAuthorizedSubject(req); - try - { - onDelete(req, resp); - } - finally + HttpSession session = req.getSession(); + + HttpManagementActor actor = (HttpManagementActor) session.getAttribute(ATTR_LOG_ACTOR); + if(actor == null) { - clearAuthorizedSubject(); + actor = new HttpManagementActor(_rootLogger, req.getRemoteAddr(), req.getRemotePort()); + session.setAttribute(ATTR_LOG_ACTOR, actor); } + + return actor; } - protected void onDelete(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException + protected Subject getSubjectFromSession(HttpSession session) { - super.doDelete(req, resp); + return (Subject)session.getAttribute(ATTR_SUBJECT); } + protected void setSubjectInSession(Subject subject, final HttpSession session) + { + session.setAttribute(ATTR_SUBJECT, subject); + } protected Broker getBroker() { diff --git a/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/LogRecordsServlet.java b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/LogRecordsServlet.java index 404793b592..04eda2a787 100644 --- a/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/LogRecordsServlet.java +++ b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/LogRecordsServlet.java @@ -44,7 +44,7 @@ public class LogRecordsServlet extends AbstractServlet } @Override - protected void onGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + protected void doGetWithSubjectAndActor(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { response.setContentType("application/json"); response.setStatus(HttpServletResponse.SC_OK); diff --git a/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MessageContentServlet.java b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MessageContentServlet.java index bc87f0bcc5..ae794472bf 100644 --- a/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MessageContentServlet.java +++ b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MessageContentServlet.java @@ -48,7 +48,7 @@ public class MessageContentServlet extends AbstractServlet } @Override - protected void onGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + protected void doGetWithSubjectAndActor(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { if(request.getPathInfo() != null && request.getPathInfo().length()>0 && request.getPathInfo().substring(1).split("/").length > 2) diff --git a/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MessageServlet.java b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MessageServlet.java index 6e7bc1d935..3920443b07 100644 --- a/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MessageServlet.java +++ b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MessageServlet.java @@ -62,7 +62,7 @@ public class MessageServlet extends AbstractServlet } @Override - protected void onGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + protected void doGetWithSubjectAndActor(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { if(request.getPathInfo() != null && request.getPathInfo().length()>0 && request.getPathInfo().substring(1).split("/").length > 2) @@ -400,7 +400,7 @@ public class MessageServlet extends AbstractServlet * POST moves or copies messages to the given queue from a queue specified in the posted JSON data */ @Override - protected void onPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException + protected void doPostWithSubjectAndActor(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { try @@ -450,7 +450,7 @@ public class MessageServlet extends AbstractServlet * DELETE removes messages from the queue */ @Override - protected void onDelete(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException + protected void doDeleteWithSubjectAndActor(HttpServletRequest request, HttpServletResponse response) { final Queue sourceQueue = getQueueFromRequest(request); diff --git a/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/RestServlet.java b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/RestServlet.java index 6a79916d07..f2ca25d664 100644 --- a/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/RestServlet.java +++ b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/RestServlet.java @@ -31,7 +31,6 @@ import org.apache.qpid.server.model.*; import org.codehaus.jackson.map.ObjectMapper; import org.codehaus.jackson.map.SerializationConfig; - public class RestServlet extends AbstractServlet { private static final Logger LOGGER = Logger.getLogger(RestServlet.class); @@ -285,7 +284,7 @@ public class RestServlet extends AbstractServlet } @Override - protected void onGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException + protected void doGetWithSubjectAndActor(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("application/json"); response.setStatus(HttpServletResponse.SC_OK); @@ -319,7 +318,7 @@ public class RestServlet extends AbstractServlet } @Override - protected void onPut(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException + protected void doPutWithSubjectAndActor(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("application/json"); @@ -336,7 +335,8 @@ public class RestServlet extends AbstractServlet if(names.size() != _hierarchy.length) { - throw new IllegalArgumentException("Path to object to create must be fully specified"); + throw new IllegalArgumentException("Path to object to create must be fully specified. " + + "Found " + names.size() + " expecting " + _hierarchy.length); } } @@ -428,8 +428,11 @@ public class RestServlet extends AbstractServlet || (obj.getName().equals(providedObject.get("name")) && equalParents(obj, otherParents))) { doUpdate(obj, providedObject); + response.setStatus(HttpServletResponse.SC_OK); + return; } } + theParent.createChild(objClass, providedObject, otherParents); } catch (RuntimeException e) @@ -464,11 +467,12 @@ public class RestServlet extends AbstractServlet { if (e.getCause() instanceof AMQSecurityException) { + LOGGER.debug("Caught AMQSecurityException", e); response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); } else { - LOGGER.warn("Unexpected exception is caught", e); + LOGGER.warn("Caught exception", e); // TODO response.setStatus(HttpServletResponse.SC_CONFLICT); @@ -476,7 +480,7 @@ public class RestServlet extends AbstractServlet } @Override - protected void onDelete(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException + protected void doDeleteWithSubjectAndActor(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("application/json"); response.setStatus(HttpServletResponse.SC_OK); diff --git a/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/SaslServlet.java b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/SaslServlet.java index 1b78611a50..b5929875ff 100644 --- a/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/SaslServlet.java +++ b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/SaslServlet.java @@ -27,8 +27,8 @@ import org.codehaus.jackson.map.SerializationConfig; import org.apache.log4j.Logger; import org.apache.qpid.server.model.Broker; import org.apache.qpid.server.registry.ApplicationRegistry; -import org.apache.qpid.server.security.auth.manager.AuthenticationManager; -import org.apache.qpid.server.security.auth.sasl.UsernamePrincipal; +import org.apache.qpid.server.security.SubjectCreator; +import org.apache.qpid.server.security.auth.AuthenticatedPrincipal; import javax.security.auth.Subject; import javax.security.sasl.SaslException; @@ -67,7 +67,7 @@ public class SaslServlet extends AbstractServlet super(broker); } - protected void onGet(HttpServletRequest request, HttpServletResponse response) throws + protected void doGetWithSubjectAndActor(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { @@ -79,15 +79,16 @@ public class SaslServlet extends AbstractServlet response.setDateHeader ("Expires", 0); HttpSession session = request.getSession(); - Random rand = getRandom(session); + getRandom(session); - AuthenticationManager authManager = ApplicationRegistry.getInstance().getAuthenticationManager(getSocketAddress(request)); - String[] mechanisms = authManager.getMechanisms().split(" "); + SubjectCreator subjectCreator = ApplicationRegistry.getInstance().getSubjectCreator(getSocketAddress(request)); + String[] mechanisms = subjectCreator.getMechanisms().split(" "); Map<String, Object> outputObject = new LinkedHashMap<String, Object>(); - final Subject subject = (Subject) session.getAttribute("subject"); + + final Subject subject = getSubjectFromSession(session); if(subject != null) { - final Principal principal = subject.getPrincipals().iterator().next(); + Principal principal = AuthenticatedPrincipal.getAuthenticatedPrincipalFromSubject(subject); outputObject.put("user", principal.getName()); } else if (request.getRemoteUser() != null) @@ -121,8 +122,7 @@ public class SaslServlet extends AbstractServlet @Override - protected void onPost(final HttpServletRequest request, final HttpServletResponse response) - throws ServletException, IOException + protected void doPostWithSubjectAndActor(final HttpServletRequest request, final HttpServletResponse response) throws IOException { try { @@ -137,14 +137,14 @@ public class SaslServlet extends AbstractServlet String id = request.getParameter("id"); String saslResponse = request.getParameter("response"); - AuthenticationManager authManager = ApplicationRegistry.getInstance().getAuthenticationManager(getSocketAddress(request)); + SubjectCreator subjectCreator = ApplicationRegistry.getInstance().getSubjectCreator(getSocketAddress(request)); if(mechanism != null) { if(id == null) { - SaslServer saslServer = authManager.createSaslServer(mechanism, request.getServerName(), null/*TODO*/); - evaluateSaslResponse(response, session, saslResponse, saslServer); + SaslServer saslServer = subjectCreator.createSaslServer(mechanism, request.getServerName(), null/*TODO*/); + evaluateSaslResponse(response, session, saslResponse, saslServer, subjectCreator); } else { @@ -152,9 +152,7 @@ public class SaslServlet extends AbstractServlet session.removeAttribute(ATTR_ID); session.removeAttribute(ATTR_SASL_SERVER); session.removeAttribute(ATTR_EXPIRY); - } - } else { @@ -163,8 +161,7 @@ public class SaslServlet extends AbstractServlet if(id.equals(session.getAttribute(ATTR_ID)) && System.currentTimeMillis() < (Long) session.getAttribute(ATTR_EXPIRY)) { SaslServer saslServer = (SaslServer) session.getAttribute(ATTR_SASL_SERVER); - evaluateSaslResponse(response, session, saslResponse, saslServer); - + evaluateSaslResponse(response, session, saslResponse, saslServer, subjectCreator); } else { @@ -180,7 +177,6 @@ public class SaslServlet extends AbstractServlet session.removeAttribute(ATTR_ID); session.removeAttribute(ATTR_SASL_SERVER); session.removeAttribute(ATTR_EXPIRY); - } } } @@ -199,7 +195,7 @@ public class SaslServlet extends AbstractServlet private void evaluateSaslResponse(final HttpServletResponse response, final HttpSession session, - final String saslResponse, final SaslServer saslServer) throws IOException + final String saslResponse, final SaslServer saslServer, SubjectCreator subjectCreator) throws IOException { final String id; byte[] challenge; @@ -209,7 +205,6 @@ public class SaslServlet extends AbstractServlet } catch(SaslException e) { - session.removeAttribute(ATTR_ID); session.removeAttribute(ATTR_SASL_SERVER); session.removeAttribute(ATTR_EXPIRY); @@ -220,16 +215,14 @@ public class SaslServlet extends AbstractServlet if(saslServer.isComplete()) { - final Subject subject = new Subject(); - subject.getPrincipals().add(new UsernamePrincipal(saslServer.getAuthorizationID())); - session.setAttribute("subject", subject); + Subject subject = subjectCreator.createSubjectWithGroups(saslServer.getAuthorizationID()); + + setSubjectInSession(subject, session); session.removeAttribute(ATTR_ID); session.removeAttribute(ATTR_SASL_SERVER); session.removeAttribute(ATTR_EXPIRY); response.setStatus(HttpServletResponse.SC_OK); - - } else { @@ -250,7 +243,6 @@ public class SaslServlet extends AbstractServlet ObjectMapper mapper = new ObjectMapper(); mapper.configure(SerializationConfig.Feature.INDENT_OUTPUT, true); mapper.writeValue(writer, outputObject); - } } } diff --git a/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/StructureServlet.java b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/StructureServlet.java index 60f977ca66..5f553beb26 100644 --- a/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/StructureServlet.java +++ b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/StructureServlet.java @@ -47,7 +47,7 @@ public class StructureServlet extends AbstractServlet } @Override - protected void onGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + protected void doGetWithSubjectAndActor(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { response.setContentType("application/json"); response.setStatus(HttpServletResponse.SC_OK); @@ -56,6 +56,8 @@ public class StructureServlet extends AbstractServlet response.setHeader("Pragma","no-cache"); response.setDateHeader ("Expires", 0); + // TODO filtering??? request.getParameter("filter"); // filter=1,2,3 /groups/*/* + Map<String,Object> structure = generateStructure(getBroker(), Broker.class); final PrintWriter writer = response.getWriter(); diff --git a/java/broker-plugins/management-http/src/main/java/resources/authenticationprovider/showPrincipalDatabaseAuthenticationManager.html b/java/broker-plugins/management-http/src/main/java/resources/authenticationprovider/showPrincipalDatabaseAuthenticationManager.html index baadc8c35f..e6c067fddf 100644 --- a/java/broker-plugins/management-http/src/main/java/resources/authenticationprovider/showPrincipalDatabaseAuthenticationManager.html +++ b/java/broker-plugins/management-http/src/main/java/resources/authenticationprovider/showPrincipalDatabaseAuthenticationManager.html @@ -23,7 +23,5 @@ <div class="users"></div> <button data-dojo-type="dijit.form.Button" class="addUserButton">Add User</button> <button data-dojo-type="dijit.form.Button" class="deleteUserButton">Delete Users</button> - </div> - </div> diff --git a/java/broker-plugins/management-http/src/main/java/resources/group/addGroupMember.html b/java/broker-plugins/management-http/src/main/java/resources/group/addGroupMember.html new file mode 100644 index 0000000000..0372468f91 --- /dev/null +++ b/java/broker-plugins/management-http/src/main/java/resources/group/addGroupMember.html @@ -0,0 +1,37 @@ +<!-- + - + - 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. + - + --> +<div class="dijitHidden"> + <div data-dojo-type="dijit.Dialog" style="width:600px;" data-dojo-props="title:'Add Group Member'" id="addGroupMember"> + <form id="formAddGroupMember" method="post" dojoType="dijit.form.Form"> + <table cellpadding="0" cellspacing="2"> + <tr> + <td valign="top"><strong>Name*: </strong></td> + <td><input type="text" required="true" name="name" id="formAddGroupMember.name" placeholder="Name" + dojoType="dijit.form.ValidationTextBox" missingMessage="A name must be supplied" /></td> + </tr> + </table> + <br/> + + <!-- submit buttons --> + <input type="submit" value="Add Group Member" label="Add Group Member" dojoType="dijit.form.Button" /> + </form> + </div> +</div> diff --git a/java/broker-plugins/management-http/src/main/java/resources/group/showGroup.html b/java/broker-plugins/management-http/src/main/java/resources/group/showGroup.html new file mode 100644 index 0000000000..4fddf727d0 --- /dev/null +++ b/java/broker-plugins/management-http/src/main/java/resources/group/showGroup.html @@ -0,0 +1,30 @@ +<!-- + - + - 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. + - + --> +<div class="group"> + <span style="">Name:</span><span class="name" style="position:absolute; left:6em"></span> + <br/> + <div data-dojo-type="dijit.TitlePane" data-dojo-props="title: 'Group Members'"> + <div class="groupMembers"></div> + <button data-dojo-type="dijit.form.Button" class="addGroupMemberButton" type="button">Add Group Member</button> + <button data-dojo-type="dijit.form.Button" class="removeGroupMemberButton" type="button">Remove Group Members</button> + </div> +</div> + diff --git a/java/broker-plugins/management-http/src/main/java/resources/groupprovider/addGroup.html b/java/broker-plugins/management-http/src/main/java/resources/groupprovider/addGroup.html new file mode 100644 index 0000000000..8d3431808a --- /dev/null +++ b/java/broker-plugins/management-http/src/main/java/resources/groupprovider/addGroup.html @@ -0,0 +1,38 @@ +<!-- + - + - 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. + - + --> +<div class="dijitHidden"> + <div data-dojo-type="dijit.Dialog" style="width:600px;" data-dojo-props="title:'Add Group'" id="addGroup"> + <form id="formAddGroup" method="post" dojoType="dijit.form.Form"> + <table cellpadding="0" cellspacing="2"> + <tr> + <td valign="top"><strong>Group Name*: </strong></td> + <td><input type="text" required="true" name="name" id="formAddGroup.name" placeholder="Group Name" + dojoType="dijit.form.ValidationTextBox" missingMessage="A name must be supplied" /></td> + </tr> + </table> + <br/> + + <!-- submit buttons --> + <input type="submit" value="Create Group" label="Create Group" dojoType="dijit.form.Button" /> + + </form> + </div> +</div> diff --git a/java/broker-plugins/management-http/src/main/java/resources/groupprovider/showFileGroupManager.html b/java/broker-plugins/management-http/src/main/java/resources/groupprovider/showFileGroupManager.html new file mode 100644 index 0000000000..734e8b5419 --- /dev/null +++ b/java/broker-plugins/management-http/src/main/java/resources/groupprovider/showFileGroupManager.html @@ -0,0 +1,28 @@ +<!-- + - + - 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. + - + --> +<div class="FileGroupManager"> + <div data-dojo-type="dijit.TitlePane" data-dojo-props="title: 'Groups'"> + <div class="groups"></div> + <button data-dojo-type="dijit.form.Button" class="addGroupButton">Add Group</button> + <button data-dojo-type="dijit.form.Button" class="deleteGroupButton">Delete Groups</button> + </div> + +</div> diff --git a/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/util.js b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/util.js index 08fdf5c99b..5557c37a2c 100644 --- a/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/util.js +++ b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/util.js @@ -58,10 +58,10 @@ define(["dojo/_base/xhr"], return exchangeName == null || exchangeName == "" || "<<default>>" == exchangeName || exchangeName.indexOf("amq.") == 0 || exchangeName.indexOf("qpid.") == 0; }; - util.deleteGridSelections = function(updater, gridName, url, confirmationMessageStart) + util.deleteGridSelections = function(updater, grid, url, confirmationMessageStart) { - var grid = updater[gridName].grid; var data = grid.selection.getSelected(); + if(data.length) { var confirmationMessage = null; @@ -103,7 +103,8 @@ define(["dojo/_base/xhr"], xhr.del({url: query, sync: true, handleAs: "json"}).then( function(data) { - grid.setQuery({id: "*"}); + // TODO why query *?? + //grid.setQuery({id: "*"}); grid.selection.deselectAll(); updater.update(); }, diff --git a/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Exchange.js b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Exchange.js index 37bae1ef8e..5a5a6515ef 100644 --- a/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Exchange.js +++ b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Exchange.js @@ -115,7 +115,7 @@ define(["dojo/_base/xhr", { util.deleteGridSelections( this.exchangeUpdater, - "bindingsGrid", + that.exchangeUpdater.bindingsGrid.grid, "rest/binding/"+ encodeURIComponent(this.getVirtualHostName()) + "/" + encodeURIComponent(this.name), "Are you sure you want to delete binding for queue"); } diff --git a/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/GroupProvider.js b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/GroupProvider.js new file mode 100644 index 0000000000..4e05f4b0ea --- /dev/null +++ b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/GroupProvider.js @@ -0,0 +1,109 @@ +/* + * + * 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. + * + */ +define(["dojo/_base/xhr", + "dojo/parser", + "dojo/query", + "dojo/_base/connect", + "qpid/common/properties", + "qpid/common/updater", + "qpid/common/util", + "qpid/common/UpdatableStore", + "dojox/grid/EnhancedGrid", + "dojox/grid/enhanced/plugins/Pagination", + "dojox/grid/enhanced/plugins/IndirectSelection", + "dojo/domReady!"], + function (xhr, parser, query, connect, properties, updater, util, UpdatableStore, EnhancedGrid) { + + function GroupProvider(name, parent, controller) { + this.name = name; + this.controller = controller; + this.modelObj = { type: "groupprovider", name: name }; + if(parent) { + this.modelObj.parent = {}; + this.modelObj.parent[ parent.type] = parent; + } + } + + GroupProvider.prototype.getTitle = function() { + return "GroupProvider"; + }; + + GroupProvider.prototype.open = function(contentPane) { + var that = this; + this.contentPane = contentPane; + xhr.get({url: "showGroupProvider.html", + sync: true, + load: function(data) { + contentPane.containerNode.innerHTML = data; + parser.parse(contentPane.containerNode); + + that.groupProviderAdapter = new GroupProviderUpdater(contentPane.containerNode, that.modelObj, that.controller); + + updater.add( that.groupProviderAdapter ); + + that.groupProviderAdapter.update(); + + }}); + }; + + GroupProvider.prototype.close = function() { + updater.remove( this.groupProviderAdapter ); + }; + + function GroupProviderUpdater(node, groupProviderObj, controller) + { + this.controller = controller; + this.name = query(".name", node)[0]; + this.query = "rest/groupprovider/"+encodeURIComponent(groupProviderObj.name); + + var that = this; + + xhr.get({url: this.query, sync: properties.useSyncGet, handleAs: "json"}) + .then(function(data) + { + that.groupProviderData = data[0]; + + util.flattenStatistics( that.groupProviderData ); + + that.updateHeader(); + + require(["qpid/management/groupprovider/"+that.groupProviderData.type], + function(SpecificProvider) { + that.details = new SpecificProvider(node, groupProviderObj, controller); + that.details.update(); + }); + + }); + + } + + GroupProviderUpdater.prototype.updateHeader = function() + { + this.name.innerHTML = this.groupProviderData[ "name" ]; + }; + + GroupProviderUpdater.prototype.update = function() + { + var that = this; + }; + + return GroupProvider; + }); diff --git a/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/VirtualHost.js b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/VirtualHost.js index 957f2381cf..2efc46476d 100644 --- a/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/VirtualHost.js +++ b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/VirtualHost.js @@ -72,7 +72,7 @@ define(["dojo/_base/xhr", function(evt){ util.deleteGridSelections( that.vhostUpdater, - "queuesGrid", + that.vhostUpdater.queuesGrid.grid, "rest/queue/"+ encodeURIComponent(that.name), "Are you sure you want to delete queue"); } @@ -87,7 +87,7 @@ define(["dojo/_base/xhr", { util.deleteGridSelections( that.vhostUpdater, - "exchangesGrid", + that.vhostUpdater.exchangesGrid.grid, "rest/exchange/"+ encodeURIComponent(that.name), "Are you sure you want to delete exchange"); } diff --git a/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/controller.js b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/controller.js index 1aa05a5a3c..5d3a666760 100644 --- a/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/controller.js +++ b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/controller.js @@ -27,13 +27,17 @@ define(["dojo/dom", "qpid/management/Queue", "qpid/management/Connection", "qpid/management/AuthenticationProvider", + "qpid/management/GroupProvider", + "qpid/management/group/Group", "dojo/ready", "dojo/domReady!"], - function (dom, registry, ContentPane, Broker, VirtualHost, Exchange, Queue, Connection, AuthProvider, ready) { + function (dom, registry, ContentPane, Broker, VirtualHost, Exchange, Queue, Connection, AuthProvider, GroupProvider, Group, ready) { var controller = {}; var constructors = { broker: Broker, virtualhost: VirtualHost, exchange: Exchange, - queue: Queue, connection: Connection, authenticationprovider: AuthProvider }; + queue: Queue, connection: Connection, + authenticationprovider: AuthProvider, groupprovider: GroupProvider, + group: Group }; var tabDiv = dom.byId("managedViews"); diff --git a/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/group/Group.js b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/group/Group.js new file mode 100644 index 0000000000..801f35c7aa --- /dev/null +++ b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/group/Group.js @@ -0,0 +1,215 @@ +/* + * + * 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. + * + */ +define(["dojo/_base/xhr", + "dojo/parser", + "dojo/query", + "dijit/registry", + "dojo/_base/connect", + "dojo/_base/event", + "dojo/json", + "qpid/common/properties", + "qpid/common/updater", + "qpid/common/util", + "qpid/common/formatter", + "qpid/common/UpdatableStore", + "dojo/store/JsonRest", + "dojox/grid/EnhancedGrid", + "dojo/data/ObjectStore", + "qpid/management/group/addGroupMember", + "dojox/grid/enhanced/plugins/Pagination", + "dojox/grid/enhanced/plugins/IndirectSelection", + "dojo/domReady!"], + function (xhr, parser, query, registry, connect, event, json, properties, updater, util, formatter, + UpdatableStore, JsonRest, EnhancedGrid, ObjectStore, addGroupMember) { + + function Group(name, parent, controller) { + this.name = name; + this.controller = controller; + this.modelObj = { type: "group", name: name }; + + if(parent) { + this.modelObj.parent = {}; + this.modelObj.parent[ parent.type] = parent; + } + } + + Group.prototype.getGroupName = function() + { + return this.name; + }; + + + Group.prototype.getGroupProviderName = function() + { + return this.modelObj.parent.groupprovider.name; + }; + + Group.prototype.getTitle = function() + { + return "Group: " + this.name; + }; + + Group.prototype.open = function(contentPane) { + var that = this; + this.contentPane = contentPane; + + xhr.get({url: "group/showGroup.html", + sync: true, + load: function(data) { + contentPane.containerNode.innerHTML = data; + parser.parse(contentPane.containerNode); + + that.groupUpdater = new GroupUpdater(contentPane.containerNode, that, that.controller); + + updater.add( that.groupUpdater ); + + that.groupUpdater.update(); + + var addGroupMemberButton = query(".addGroupMemberButton", contentPane.containerNode)[0]; + connect.connect(registry.byNode(addGroupMemberButton), "onClick", + function(evt){ + addGroupMember.show(that.getGroupProviderName(), that.getGroupName()) + } + ); + + var removeGroupMemberButton = query(".removeGroupMemberButton", contentPane.containerNode)[0]; + connect.connect(registry.byNode(removeGroupMemberButton), "onClick", + function(evt){ + util.deleteGridSelections( + that.groupUpdater, + that.groupUpdater.groupMembersUpdatableStore.grid, + "rest/groupmember/"+ encodeURIComponent(that.getGroupProviderName()) + + "/" + encodeURIComponent(that.getGroupName()), + "Are you sure you want to remove group member"); + } + ); + }}); + }; + + Group.prototype.close = function() { + updater.remove( this.groupUpdater ); + }; + + function GroupUpdater(containerNode, groupObj, controller) + { + var that = this; + + function findNode(name) { + return query("." + name, containerNode)[0]; + } + + function storeNodes(names) + { + for(var i = 0; i < names.length; i++) { + that[names[i]] = findNode(names[i]); + } + } + + storeNodes(["name", + "state", + "durable", + "lifetimePolicy", + "type"]); + + this.query = "rest/groupmember/"+ encodeURIComponent(groupObj.getGroupProviderName()) + "/" + encodeURIComponent(groupObj.getGroupName()); + + xhr.get({url: this.query, sync: properties.useSyncGet, handleAs: "json"}).then(function(data) + { + that.groupMemberData = data; + + util.flattenStatistics( that.groupMemberData ); + + var gridProperties = { + keepSelection: true, + plugins: { + pagination: { + pageSizes: ["10", "25", "50", "100"], + description: true, + sizeSwitch: true, + pageStepper: true, + gotoButton: true, + maxPageStep: 4, + position: "bottom" + }, + indirectSelection: true + + }}; + + that.groupMembersUpdatableStore = new UpdatableStore(that.groupMemberData, findNode("groupMembers"), + [ { name: "Group Member Name", field: "name", width: "100%" }], + function(obj) + { + connect.connect(obj.grid, "onRowDblClick", obj.grid, + function(evt){ + + }); + } , gridProperties, EnhancedGrid); + + }); + + } + + GroupUpdater.prototype.update = function() + { + + var that = this; + + console.log("updater called "); + console.dir(that); + + + xhr.get({url: this.query, sync: properties.useSyncGet, handleAs: "json"}) + .then(function(data) { + that.groupMemberData = data; + + console.log("updater data "); + console.dir(that.groupMemberData); + + + util.flattenStatistics( that.groupMemberData ); + + that.groupMembersUpdatableStore.update(that.groupMemberData); + + console.log("updated grid"); + console.dir(that.groupMembersUpdatableStore.grid); + }); + }; + + Group.prototype.deleteGroupMember = function() { + if(confirm("Are you sure you want to delete group member'" +this.name+"'?")) { + var query = "rest/groupmember/"+ encodeURIComponent(this.getGroupProviderName()) + "/" + encodeURIComponent(this.name); + this.success = true + var that = this; + xhr.del({url: query, sync: true, handleAs: "json"}).then( + function(data) { + that.contentPane.onClose() + that.controller.tabContainer.removeChild(that.contentPane); + that.contentPane.destroyRecursive(); + }, + function(error) {that.success = false; that.failureReason = error;}); + if(!this.success ) { + alert("Error:" + this.failureReason); + } + } + } + + return Group; + }); diff --git a/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/group/addGroupMember.js b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/group/addGroupMember.js new file mode 100644 index 0000000000..1861cc6ffe --- /dev/null +++ b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/group/addGroupMember.js @@ -0,0 +1,108 @@ +/* + * + * 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. + * + */ +define(["dojo/_base/xhr", + "dojo/dom", + "dojo/dom-construct", + "dojo/_base/window", + "dijit/registry", + "dojo/parser", + "dojo/_base/array", + "dojo/_base/event", + 'dojo/_base/json', + "dijit/form/NumberSpinner", // required by the form + /* dojox/ validate resources */ + "dojox/validate/us", "dojox/validate/web", + /* basic dijit classes */ + "dijit/Dialog", + "dijit/form/CheckBox", "dijit/form/Textarea", + "dijit/form/FilteringSelect", "dijit/form/TextBox", + "dijit/form/ValidationTextBox", "dijit/form/DateTextBox", + "dijit/form/TimeTextBox", "dijit/form/Button", + "dijit/form/RadioButton", "dijit/form/Form", + "dijit/form/DateTextBox", + /* basic dojox classes */ + "dojox/form/BusyButton", "dojox/form/CheckedMultiSelect", + "dojo/domReady!"], + function (xhr, dom, construct, win, registry, parser, array, event, json) { + + var addGroupMember = {}; + + var node = construct.create("div", null, win.body(), "last"); + + var convertToGroupMember = function convertToGroupMember(formValues) + { + var newGroupMember = {}; + newGroupMember.name = formValues.name; + return newGroupMember; + }; + + xhr.get({url: "group/addGroupMember.html", + sync: true, + load: function(data) { + var theForm; + node.innerHTML = data; + addGroupMember.dialogNode = dom.byId("addGroupMember"); + parser.instantiate([addGroupMember.dialogNode]); + + theForm = registry.byId("formAddGroupMember"); + theForm.on("submit", function(e) { + + event.stop(e); + if(theForm.validate()){ + + var newGroupMember = convertToGroupMember(theForm.getValues()); + var that = this; + xhr.put({url: "rest/groupmember/"+encodeURIComponent(addGroupMember.groupProvider) + + "/" + encodeURIComponent(addGroupMember.group) + "/" + encodeURIComponent(newGroupMember.name), sync: true, handleAs: "json", + headers: { "Content-Type": "application/json"}, + putData: json.toJson(newGroupMember), + load: function(x) {that.success = true; }, + error: function(error) {that.success = false; that.failureReason = error;}}); + + if(this.success === true) + { + registry.byId("addGroupMember").hide(); + } + else + { + alert("Error:" + this.failureReason); + } + + return false; + + + }else{ + alert('Form contains invalid data. Please correct first'); + return false; + } + + }); + }}); + + addGroupMember.show = function(groupProvider, group) { + addGroupMember.groupProvider = groupProvider; + addGroupMember.group = group; + registry.byId("formAddGroupMember").reset(); + registry.byId("addGroupMember").show(); + }; + + return addGroupMember; + });
\ No newline at end of file diff --git a/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/groupprovider/FileGroupManager.js b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/groupprovider/FileGroupManager.js new file mode 100644 index 0000000000..44fc9702e2 --- /dev/null +++ b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/groupprovider/FileGroupManager.js @@ -0,0 +1,251 @@ +/* + * + * 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. + * + */ +define(["dojo/_base/xhr", + "dojo/dom", + "dojo/parser", + "dojo/query", + "dojo/dom-construct", + "dojo/_base/connect", + "dojo/_base/window", + "dojo/_base/event", + "dojo/_base/json", + "dijit/registry", + "qpid/common/util", + "qpid/common/properties", + "qpid/common/updater", + "qpid/common/UpdatableStore", + "dojox/grid/EnhancedGrid", + "dojox/grid/enhanced/plugins/Pagination", + "dojox/grid/enhanced/plugins/IndirectSelection", + "dojox/validate/us", "dojox/validate/web", + "dijit/Dialog", + "dijit/form/TextBox", + "dijit/form/ValidationTextBox", + "dijit/form/TimeTextBox", "dijit/form/Button", + "dijit/form/Form", + "dijit/form/DateTextBox", + "dojo/domReady!"], + function (xhr, dom, parser, query, construct, connect, win, event, json, registry, util, properties, updater, UpdatableStore, EnhancedGrid) { + function DatabaseGroupManager(containerNode, groupProviderObj, controller) { + var node = construct.create("div", null, containerNode, "last"); + var that = this; + this.name = groupProviderObj.name; + xhr.get({url: "groupprovider/showFileGroupManager.html", + sync: true, + load: function(data) { + node.innerHTML = data; + parser.parse(node); + + + that.groupDatabaseUpdater= new GroupProviderUpdater(node, groupProviderObj, controller); + + updater.add( that.groupDatabaseUpdater); + + that.groupDatabaseUpdater.update(); + + + }}); + } + + DatabaseGroupManager.prototype.update = function() { + this.groupDatabaseUpdater.update(); + }; + + DatabaseGroupManager.prototype.close = function() { + updater.remove( this.groupDatabaseUpdater ); + }; + + function GroupProviderUpdater(node, groupProviderObj, controller) + { + this.controller = controller; + this.query = "rest/groupprovider/"+encodeURIComponent(groupProviderObj.name); + this.name = groupProviderObj.name; + var that = this; + + xhr.get({url: this.query, sync: properties.useSyncGet, handleAs: "json"}) + .then(function(data) { + that.groupProviderData = data[0]; + + util.flattenStatistics( that.groupProviderData ); + + var groupDiv = query(".groups")[0]; + + var gridProperties = { + height: 400, + keepSelection: true, + plugins: { + pagination: { + pageSizes: ["10", "25", "50", "100"], + description: true, + sizeSwitch: true, + pageStepper: true, + gotoButton: true, + maxPageStep: 4, + position: "bottom" + }, + indirectSelection: true + + }}; + + + that.groupsGrid = + new UpdatableStore(that.groupProviderData.groups, groupDiv, + [ { name: "Group Name", field: "name", width: "100%" } + ], null, gridProperties, EnhancedGrid); + + + var addGroupButton = query(".addGroupButton", node)[0]; + connect.connect(registry.byNode(addGroupButton), "onClick", function(evt){ addGroup.show(groupProviderObj.name) }); + + var deleteMessagesButton = query(".deleteGroupButton", node)[0]; + var deleteWidget = registry.byNode(deleteMessagesButton); + connect.connect(deleteWidget, "onClick", + function(evt){ + event.stop(evt); + that.deleteGroups(); + }); + }); + } + + GroupProviderUpdater.prototype.deleteGroups = function() + { + var grid = this.groupsGrid.grid; + var data = grid.selection.getSelected(); + if(data.length) { + var that = this; + if(confirm("Delete " + data.length + " groups?")) { + var i, queryParam; + for(i = 0; i<data.length; i++) { + if(queryParam) { + queryParam += "&"; + } else { + queryParam = "?"; + } + + queryParam += "id=" + data[i].id; + } + var query = "rest/group/"+ encodeURIComponent(that.name) + + queryParam; + that.success = true + xhr.del({url: query, sync: true, handleAs: "json"}).then( + function(data) { + grid.setQuery({id: "*"}); + grid.selection.deselectAll(); + that.update(); + }, + function(error) {that.success = false; that.failureReason = error;}); + if(!that.success ) { + alert("Error:" + this.failureReason); + } + } +} + }; + + GroupProviderUpdater.prototype.update = function() + { + + var that = this; + + xhr.get({url: this.query, sync: properties.useSyncGet, handleAs: "json"}) + .then(function(data) { + that.groupProviderData = data[0]; + util.flattenStatistics( that.groupProviderData ); + + that.groupsGrid.update(that.groupProviderData.groups); + + }); + + + }; + + var addGroup = {}; + + var node = construct.create("div", null, win.body(), "last"); + + var convertToGroup = function convertToGroup(formValues) { + var newGroup = {}; + newGroup.name = formValues.name; + for(var propName in formValues) + { + if(formValues.hasOwnProperty(propName)) { + if(formValues[ propName ] !== "") { + newGroup[ propName ] = formValues[propName]; + } + } + } + + return newGroup; + }; + + + xhr.get({url: "groupprovider/addGroup.html", + sync: true, + load: function(data) { + var theForm; + node.innerHTML = data; + addGroup.dialogNode = dom.byId("addGroup"); + parser.instantiate([addGroup.dialogNode]); + + var that = this; + + theForm = registry.byId("formAddGroup"); + theForm.on("submit", function(e) { + + event.stop(e); + if(theForm.validate()){ + + var newGroup = convertToGroup(theForm.getValues()); + + + var url = "rest/group/"+encodeURIComponent(addGroup.groupProvider) + + "/"+encodeURIComponent(newGroup.name); + + xhr.put({url: url, sync: true, handleAs: "json", + headers: { "Content-Type": "application/json"}, + putData: json.toJson(newGroup), + load: function(x) {that.success = true; }, + error: function(error) {that.success = false; that.failureReason = error;}}); + + if(that.success === true) { + registry.byId("addGroup").hide(); + } else { + alert("Error:" + that.failureReason); + } + + return false; + + + }else{ + alert('Form contains invalid data. Please correct first'); + return false; + } + + }); + }}); + + addGroup.show = function(groupProvider) { + addGroup.groupProvider = groupProvider; + registry.byId("formAddGroup").reset(); + registry.byId("addGroup").show(); + }; + + return DatabaseGroupManager; + }); diff --git a/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/treeView.js b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/treeView.js index b1d4abf8c1..59356cfce1 100644 --- a/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/treeView.js +++ b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/treeView.js @@ -273,10 +273,12 @@ define(["dojo/_base/xhr", controller.show("port", details.port, { type: "virtualhost", name: details.virtualhost, parent: {broker: {type:"broker", name:""}}}); } else if (details.type == 'authenticationprovider') { controller.show("authenticationprovider", details.authenticationprovider, {broker: {type:"broker", name:""}}); + } else if (details.type == 'groupprovider') { + controller.show("groupprovider", details.groupprovider, {broker: {type:"broker", name:""}}); + } else if (details.type == 'group') { + controller.show("group", details.group, { type: "groupprovider", name: details.groupprovider, parent: {broker: {type:"broker", name:""}}}); } - - }; TreeViewModel.prototype.update = function () { diff --git a/java/broker-plugins/management-http/src/main/java/resources/showGroupProvider.html b/java/broker-plugins/management-http/src/main/java/resources/showGroupProvider.html new file mode 100644 index 0000000000..914857db5c --- /dev/null +++ b/java/broker-plugins/management-http/src/main/java/resources/showGroupProvider.html @@ -0,0 +1,25 @@ +<!-- + - + - 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. + - + --> +<div class="groupProvider"> + <span style="">Name:</span><span class="name" style="position:absolute; left:6em"></span> + <br/> + <span style="">Type:</span><span class="type" style="position:absolute; left:6em"></span> +</div>
\ No newline at end of file diff --git a/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/AuthenticationProviderRestTest.java b/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/AuthenticationProviderRestTest.java index 5e6d9a998a..86533b76b4 100644 --- a/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/AuthenticationProviderRestTest.java +++ b/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/AuthenticationProviderRestTest.java @@ -33,13 +33,13 @@ public class AuthenticationProviderRestTest extends QpidRestTestCase public void testGet() throws Exception { - List<Map<String, Object>> providerDetails = getJsonAsList("/rest/authenticationprovider"); + List<Map<String, Object>> providerDetails = getRestTestHelper().getJsonAsList("/rest/authenticationprovider"); assertNotNull("Providers details cannot be null", providerDetails); assertEquals("Unexpected number of providers", 1, providerDetails.size()); for (Map<String, Object> provider : providerDetails) { assertProvider("PrincipalDatabaseAuthenticationManager", provider); - Map<String, Object> data = getJsonAsSingletonList("/rest/authenticationprovider/" + Map<String, Object> data = getRestTestHelper().getJsonAsSingletonList("/rest/authenticationprovider/" + provider.get(AuthenticationProvider.NAME)); assertNotNull("Cannot load data for " + provider.get(AuthenticationProvider.NAME), data); assertProvider("PrincipalDatabaseAuthenticationManager", data); diff --git a/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/BindingRestTest.java b/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/BindingRestTest.java index 1ed0d97185..c2f11ed237 100644 --- a/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/BindingRestTest.java +++ b/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/BindingRestTest.java @@ -32,7 +32,7 @@ public class BindingRestTest extends QpidRestTestCase public void testGetAllBindings() throws Exception { - List<Map<String, Object>> bindings = getJsonAsList("/rest/binding"); + List<Map<String, Object>> bindings = getRestTestHelper().getJsonAsList("/rest/binding"); assertNotNull("Bindings cannot be null", bindings); assertTrue("Unexpected number of bindings", bindings.size() >= EXPECTED_HOSTS.length * EXPECTED_QUEUES.length); for (Map<String, Object> binding : bindings) @@ -43,7 +43,7 @@ public class BindingRestTest extends QpidRestTestCase public void testGetVirtualHostBindings() throws Exception { - List<Map<String, Object>> bindings = getJsonAsList("/rest/binding/test"); + List<Map<String, Object>> bindings = getRestTestHelper().getJsonAsList("/rest/binding/test"); assertNotNull("Bindings cannot be null", bindings); assertEquals("Unexpected number of bindings", EXPECTED_QUEUES.length * 2, bindings.size()); for (String queueName : EXPECTED_QUEUES) @@ -52,31 +52,31 @@ public class BindingRestTest extends QpidRestTestCase searchAttributes.put(Binding.NAME, queueName); searchAttributes.put(Binding.EXCHANGE, "amq.direct"); - Map<String, Object> binding = find(searchAttributes, bindings); + Map<String, Object> binding = getRestTestHelper().find(searchAttributes, bindings); Asserts.assertBinding(queueName, "amq.direct", binding); searchAttributes.put(Binding.EXCHANGE, "<<default>>"); - binding = find(searchAttributes, bindings); + binding = getRestTestHelper().find(searchAttributes, bindings); Asserts.assertBinding(queueName, "<<default>>", binding); } } public void testGetVirtualHostExchangeBindings() throws Exception { - List<Map<String, Object>> bindings = getJsonAsList("/rest/binding/test/amq.direct"); + List<Map<String, Object>> bindings = getRestTestHelper().getJsonAsList("/rest/binding/test/amq.direct"); assertNotNull("Bindings cannot be null", bindings); assertEquals("Unexpected number of bindings", EXPECTED_QUEUES.length, bindings.size()); for (String queueName : EXPECTED_QUEUES) { - Map<String, Object> binding = find(Binding.NAME, queueName, bindings); + Map<String, Object> binding = getRestTestHelper().find(Binding.NAME, queueName, bindings); Asserts.assertBinding(queueName, "amq.direct", binding); } } public void testGetVirtualHostExchangeQueueBindings() throws Exception { - List<Map<String, Object>> bindings = getJsonAsList("/rest/binding/test/amq.direct/queue"); + List<Map<String, Object>> bindings = getRestTestHelper().getJsonAsList("/rest/binding/test/amq.direct/queue"); assertNotNull("Bindings cannot be null", bindings); assertEquals("Unexpected number of bindings", 1, bindings.size()); Asserts.assertBinding("queue", "amq.direct", bindings.get(0)); @@ -85,25 +85,25 @@ public class BindingRestTest extends QpidRestTestCase public void testDeleteBinding() throws Exception { - List<Map<String, Object>> bindings = getJsonAsList("/rest/binding/test/amq.direct/queue/queue"); + List<Map<String, Object>> bindings = getRestTestHelper().getJsonAsList("/rest/binding/test/amq.direct/queue/queue"); assertEquals("Unexpected number of bindings", 1, bindings.size()); Asserts.assertBinding("queue", "amq.direct", bindings.get(0)); - HttpURLConnection connection = openManagementConection("/rest/binding/test/amq.direct/queue/queue", "DELETE"); + HttpURLConnection connection = getRestTestHelper().openManagementConnection("/rest/binding/test/amq.direct/queue/queue", "DELETE"); connection.connect(); assertEquals("Unexpected response code", 200, connection.getResponseCode()); - bindings = getJsonAsList("/rest/binding/test/amq.direct/queue/queue"); + bindings = getRestTestHelper().getJsonAsList("/rest/binding/test/amq.direct/queue/queue"); assertEquals("Binding should be deleted", 0, bindings.size()); } public void testDeleteBindingById() throws Exception { - Map<String, Object> binding = getJsonAsSingletonList("/rest/binding/test/amq.direct/queue"); - HttpURLConnection connection = openManagementConection("/rest/binding/test/amq.direct?id=" + binding.get(Binding.ID), "DELETE"); + Map<String, Object> binding = getRestTestHelper().getJsonAsSingletonList("/rest/binding/test/amq.direct/queue"); + HttpURLConnection connection = getRestTestHelper().openManagementConnection("/rest/binding/test/amq.direct?id=" + binding.get(Binding.ID), "DELETE"); connection.connect(); assertEquals("Unexpected response code", 200, connection.getResponseCode()); - List<Map<String, Object>> bindings = getJsonAsList("/rest/binding/test/amq.direct/queue"); + List<Map<String, Object>> bindings = getRestTestHelper().getJsonAsList("/rest/binding/test/amq.direct/queue"); assertEquals("Binding should be deleted", 0, bindings.size()); } @@ -115,13 +115,13 @@ public class BindingRestTest extends QpidRestTestCase bindingData.put(Binding.QUEUE, "queue"); bindingData.put(Binding.EXCHANGE, "amq.direct"); - HttpURLConnection connection = openManagementConection("/rest/binding/test/amq.direct/queue/" + bindingName, "PUT"); + HttpURLConnection connection = getRestTestHelper().openManagementConnection("/rest/binding/test/amq.direct/queue/" + bindingName, "PUT"); connection.connect(); - writeJsonRequest(connection, bindingData); + getRestTestHelper().writeJsonRequest(connection, bindingData); int responseCode = connection.getResponseCode(); connection.disconnect(); assertEquals("Unexpected response code", 201, responseCode); - Map<String, Object> binding = getJsonAsSingletonList("/rest/binding/test/amq.direct/queue/" + bindingName); + Map<String, Object> binding = getRestTestHelper().getJsonAsSingletonList("/rest/binding/test/amq.direct/queue/" + bindingName); Asserts.assertBinding(bindingName, "queue", "amq.direct", binding); } diff --git a/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/BrokerRestHttpsTest.java b/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/BrokerRestHttpsTest.java index 4bbe9155cd..08b5863004 100644 --- a/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/BrokerRestHttpsTest.java +++ b/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/BrokerRestHttpsTest.java @@ -21,13 +21,8 @@ package org.apache.qpid.server.management.plugin.servlet.rest; import java.io.IOException; -import java.net.HttpURLConnection; -import java.net.URL; import java.util.Map; -import javax.net.ssl.HttpsURLConnection; -import javax.net.ssl.SSLSocketFactory; - import org.apache.commons.configuration.ConfigurationException; import org.apache.qpid.server.model.Broker; @@ -48,37 +43,16 @@ public class BrokerRestHttpsTest extends QpidRestTestCase @Override protected void customizeConfiguration() throws ConfigurationException, IOException { + getRestTestHelper().setUseSsl(true); setConfigurationProperty("management.enabled", "true"); setConfigurationProperty("management.http.enabled", "false"); setConfigurationProperty("management.https.enabled", "true"); - setConfigurationProperty("management.https.port", Integer.toString(getHttpPort())); - } - - @Override - protected String getHostName() - { - return "localhost"; - } - - @Override - protected String getProtocol() - { - return "https"; - } - - @Override - protected HttpURLConnection openManagementConection(String path) throws IOException - { - URL url = getManagementURL(path); - HttpURLConnection httpCon = (HttpURLConnection) url.openConnection(); - ((HttpsURLConnection) httpCon).setSSLSocketFactory((SSLSocketFactory) SSLSocketFactory.getDefault()); - httpCon.setDoOutput(true); - return httpCon; + setConfigurationProperty("management.https.port", Integer.toString(getRestTestHelper().getHttpPort())); } public void testGetWithHttps() throws Exception { - Map<String, Object> brokerDetails = getJsonAsSingletonList("/rest/broker"); + Map<String, Object> brokerDetails = getRestTestHelper().getJsonAsSingletonList("/rest/broker"); Asserts.assertAttributesPresent(brokerDetails, Broker.AVAILABLE_ATTRIBUTES, Broker.BYTES_RETAINED, Broker.PROCESS_PID, Broker.SUPPORTED_STORE_TYPES, Broker.CREATED, Broker.TIME_TO_LIVE, Broker.UPDATED); diff --git a/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/BrokerRestTest.java b/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/BrokerRestTest.java index f2970e2ba9..c4cd00416b 100644 --- a/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/BrokerRestTest.java +++ b/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/BrokerRestTest.java @@ -43,7 +43,7 @@ public class BrokerRestTest extends QpidRestTestCase public void testGet() throws Exception { - Map<String, Object> brokerDetails = getJsonAsSingletonList("/rest/broker"); + Map<String, Object> brokerDetails = getRestTestHelper().getJsonAsSingletonList("/rest/broker"); assertBrokerAttributes(brokerDetails); @@ -55,9 +55,9 @@ public class BrokerRestTest extends QpidRestTestCase List<Map<String, Object>> virtualhosts = (List<Map<String, Object>>) brokerDetails.get(BROKER_VIRTUALHOSTS_ATTRIBUTE); assertEquals("Unexpected number of virtual hosts", 3, virtualhosts.size()); - Asserts.assertVirtualHost("development", find(VirtualHost.NAME, "development", virtualhosts)); - Asserts.assertVirtualHost("localhost", find(VirtualHost.NAME, "localhost", virtualhosts)); - Asserts.assertVirtualHost("test", find(VirtualHost.NAME, "test", virtualhosts)); + Asserts.assertVirtualHost("development", getRestTestHelper().find(VirtualHost.NAME, "development", virtualhosts)); + Asserts.assertVirtualHost("localhost", getRestTestHelper().find(VirtualHost.NAME, "localhost", virtualhosts)); + Asserts.assertVirtualHost("test", getRestTestHelper().find(VirtualHost.NAME, "test", virtualhosts)); @SuppressWarnings("unchecked") List<Map<String, Object>> ports = (List<Map<String, Object>>) brokerDetails.get(BROKER_PORTS_ATTRIBUTE); @@ -70,8 +70,8 @@ public class BrokerRestTest extends QpidRestTestCase String bindingAddress = (String)ports.get(0).get(Port.BINDING_ADDRESS); - Map<String, Object> amqpPort = find(Port.NAME, bindingAddress + ":" + getPort(), ports); - Map<String, Object> httpPort = find(Port.NAME, bindingAddress + ":" + getHttpPort(), ports); + Map<String, Object> amqpPort = getRestTestHelper().find(Port.NAME, bindingAddress + ":" + getPort(), ports); + Map<String, Object> httpPort = getRestTestHelper().find(Port.NAME, bindingAddress + ":" + getRestTestHelper().getHttpPort(), ports); assertNotNull("Cannot find AMQP port", amqpPort); assertNotNull("Cannot find HTTP port", httpPort); diff --git a/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/ConnectionRestTest.java b/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/ConnectionRestTest.java index 3661b94a7c..500a5770fb 100644 --- a/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/ConnectionRestTest.java +++ b/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/ConnectionRestTest.java @@ -90,14 +90,14 @@ public class ConnectionRestTest extends QpidRestTestCase public void testGetAllConnections() throws Exception { - List<Map<String, Object>> connections = getJsonAsList("/rest/connection"); + List<Map<String, Object>> connections = getRestTestHelper().getJsonAsList("/rest/connection"); assertEquals("Unexpected number of connections", 1, connections.size()); Asserts.assertConnection(connections.get(0), (AMQConnection) _connection); } public void testGetVirtualHostConnections() throws Exception { - List<Map<String, Object>> connections = getJsonAsList("/rest/connection/test"); + List<Map<String, Object>> connections = getRestTestHelper().getJsonAsList("/rest/connection/test"); assertEquals("Unexpected number of connections", 1, connections.size()); Asserts.assertConnection(connections.get(0), (AMQConnection) _connection); } @@ -107,21 +107,21 @@ public class ConnectionRestTest extends QpidRestTestCase // get connection name String connectionName = getConnectionName(); - Map<String, Object> connectionDetails = getJsonAsSingletonList("/rest/connection/test/" + Map<String, Object> connectionDetails = getRestTestHelper().getJsonAsSingletonList("/rest/connection/test/" + URLDecoder.decode(connectionName, "UTF-8")); assertConnection(connectionDetails); } public void testGetAllSessions() throws Exception { - List<Map<String, Object>> sessions = getJsonAsList("/rest/session"); + List<Map<String, Object>> sessions = getRestTestHelper().getJsonAsList("/rest/session"); assertEquals("Unexpected number of sessions", 1, sessions.size()); assertSession(sessions.get(0), (AMQSession<?, ?>) _session); } public void testGetVirtualHostSessions() throws Exception { - List<Map<String, Object>> sessions = getJsonAsList("/rest/session/test"); + List<Map<String, Object>> sessions = getRestTestHelper().getJsonAsList("/rest/session/test"); assertEquals("Unexpected number of sessions", 1, sessions.size()); assertSession(sessions.get(0), (AMQSession<?, ?>) _session); } @@ -131,7 +131,7 @@ public class ConnectionRestTest extends QpidRestTestCase // get connection name String connectionName = getConnectionName(); - List<Map<String, Object>> sessions = getJsonAsList("/rest/session/test/" + List<Map<String, Object>> sessions = getRestTestHelper().getJsonAsList("/rest/session/test/" + URLDecoder.decode(connectionName, "UTF-8")); assertEquals("Unexpected number of sessions", 1, sessions.size()); assertSession(sessions.get(0), (AMQSession<?, ?>) _session); @@ -142,7 +142,7 @@ public class ConnectionRestTest extends QpidRestTestCase // get connection name String connectionName = getConnectionName(); - List<Map<String, Object>> sessions = getJsonAsList("/rest/session/test/" + List<Map<String, Object>> sessions = getRestTestHelper().getJsonAsList("/rest/session/test/" + URLDecoder.decode(connectionName, "UTF-8") + "/" + ((AMQSession<?, ?>) _session).getChannelId()); assertEquals("Unexpected number of sessions", 1, sessions.size()); assertSession(sessions.get(0), (AMQSession<?, ?>) _session); @@ -201,7 +201,7 @@ public class ConnectionRestTest extends QpidRestTestCase private String getConnectionName() throws IOException { - Map<String, Object> hostDetails = getJsonAsSingletonList("/rest/virtualhost/test"); + Map<String, Object> hostDetails = getRestTestHelper().getJsonAsSingletonList("/rest/virtualhost/test"); @SuppressWarnings("unchecked") List<Map<String, Object>> connections = (List<Map<String, Object>>) hostDetails .get(VirtualHostRestTest.VIRTUALHOST_CONNECTIONS_ATTRIBUTE); diff --git a/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/ExchangeRestTest.java b/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/ExchangeRestTest.java index 4904d2adf3..363652d37c 100644 --- a/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/ExchangeRestTest.java +++ b/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/ExchangeRestTest.java @@ -31,7 +31,7 @@ public class ExchangeRestTest extends QpidRestTestCase { public void testGet() throws Exception { - List<Map<String, Object>> exchanges = getJsonAsList("/rest/exchange"); + List<Map<String, Object>> exchanges = getRestTestHelper().getJsonAsList("/rest/exchange"); assertNotNull("Exchanges cannot be null", exchanges); assertTrue("Unexpected number of exchanges", exchanges.size() >= EXPECTED_HOSTS.length * EXPECTED_EXCHANGES.length); for (Map<String, Object> exchange : exchanges) @@ -42,12 +42,12 @@ public class ExchangeRestTest extends QpidRestTestCase public void testGetHostExchanges() throws Exception { - List<Map<String, Object>> exchanges = getJsonAsList("/rest/exchange/test"); + List<Map<String, Object>> exchanges = getRestTestHelper().getJsonAsList("/rest/exchange/test"); assertNotNull("Users cannot be null", exchanges); assertEquals("Unexpected number of exchanges", 6, EXPECTED_EXCHANGES.length); for (String exchangeName : EXPECTED_EXCHANGES) { - Map<String, Object> exchange = find(Exchange.NAME, exchangeName, exchanges); + Map<String, Object> exchange = getRestTestHelper().find(Exchange.NAME, exchangeName, exchanges); assertExchange(exchangeName, exchange); } } @@ -56,7 +56,7 @@ public class ExchangeRestTest extends QpidRestTestCase { for (String exchangeName : EXPECTED_EXCHANGES) { - Map<String, Object> exchange = getJsonAsSingletonList("/rest/exchange/test/" + Map<String, Object> exchange = getRestTestHelper().getJsonAsSingletonList("/rest/exchange/test/" + URLDecoder.decode(exchangeName, "UTF-8")); assertExchange(exchangeName, exchange); } @@ -79,7 +79,7 @@ public class ExchangeRestTest extends QpidRestTestCase List<Map<String, Object>> bindings = (List<Map<String, Object>>) exchange.get("bindings"); for (String queueName : EXPECTED_QUEUES) { - Map<String, Object> binding = find(Binding.NAME, queueName, bindings); + Map<String, Object> binding = getRestTestHelper().find(Binding.NAME, queueName, bindings); Asserts.assertBinding(queueName, (String) exchange.get(Exchange.NAME), binding); } } diff --git a/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/GroupProviderRestTest.java b/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/GroupProviderRestTest.java new file mode 100644 index 0000000000..c2eefec395 --- /dev/null +++ b/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/GroupProviderRestTest.java @@ -0,0 +1,160 @@ +/* + * + * 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.management.plugin.servlet.rest; + +import java.io.File; +import java.io.FileOutputStream; +import java.util.List; +import java.util.Map; +import java.util.Properties; + +import org.apache.qpid.server.model.Group; +import org.apache.qpid.server.model.GroupProvider; +import org.apache.qpid.server.model.LifetimePolicy; +import org.apache.qpid.server.model.State; +import org.apache.qpid.server.model.UUIDGenerator; + +public class GroupProviderRestTest extends QpidRestTestCase +{ + private static final String FILE_GROUP_MANAGER = "FileGroupManager"; + private File _groupFile; + + @Override + public void setUp() throws Exception + { + _groupFile = createTemporaryGroupFile(); + + setConfigurationProperty("security.file-group-manager.attributes.attribute.name", "groupFile"); + setConfigurationProperty("security.file-group-manager.attributes.attribute.value", _groupFile.getAbsolutePath()); + + super.setUp(); + } + + @Override + public void tearDown() throws Exception + { + super.tearDown(); + + if (_groupFile != null) + { + if (_groupFile.exists()) + { + _groupFile.delete(); + } + } + } + + public void testGet() throws Exception + { + List<Map<String, Object>> providerDetails = getRestTestHelper().getJsonAsList("/rest/groupprovider"); + assertNotNull("Providers details cannot be null", providerDetails); + assertEquals("Unexpected number of providers", 1, providerDetails.size()); + for (Map<String, Object> provider : providerDetails) + { + assertProvider(FILE_GROUP_MANAGER, provider); + Map<String, Object> data = getRestTestHelper().getJsonAsSingletonList("/rest/groupprovider/" + + provider.get(GroupProvider.NAME)); + assertNotNull("Cannot load data for " + provider.get(GroupProvider.NAME), data); + assertProvider(FILE_GROUP_MANAGER, data); + } + } + + public void testCreateNewGroup() throws Exception + { + String groupName = "newGroup"; + + Map<String, Object> data = getRestTestHelper().getJsonAsSingletonList("/rest/groupprovider/" + FILE_GROUP_MANAGER); + assertNotNull("Cannot load data for provider", data); + + getRestTestHelper().assertNumberOfGroups(data, 1); + + getRestTestHelper().createGroup(groupName, FILE_GROUP_MANAGER); + + data = getRestTestHelper().getJsonAsSingletonList("/rest/groupprovider/" + FILE_GROUP_MANAGER); + assertNotNull("Cannot load data for provider", data); + + getRestTestHelper().assertNumberOfGroups(data, 2); + } + + public void testRemoveGroup() throws Exception + { + String groupName = "myGroup"; + + Map<String, Object> data = getRestTestHelper().getJsonAsSingletonList("/rest/groupprovider/" + FILE_GROUP_MANAGER); + assertNotNull("Cannot load data for provider", data); + + getRestTestHelper().assertNumberOfGroups(data, 1); + + getRestTestHelper().removeGroup(groupName, FILE_GROUP_MANAGER); + + data = getRestTestHelper().getJsonAsSingletonList("/rest/groupprovider/" + FILE_GROUP_MANAGER); + assertNotNull("Cannot load data for provider", data); + + getRestTestHelper().assertNumberOfGroups(data, 0); + } + + + private void assertProvider(String type, Map<String, Object> provider) + { + Asserts.assertAttributesPresent(provider, GroupProvider.AVAILABLE_ATTRIBUTES, + GroupProvider.CREATED, GroupProvider.UPDATED, GroupProvider.DESCRIPTION, + GroupProvider.TIME_TO_LIVE); + assertEquals("Unexpected value of provider attribute " + GroupProvider.STATE, State.ACTIVE.name(), + provider.get(GroupProvider.STATE)); + assertEquals("Unexpected value of provider attribute " + GroupProvider.LIFETIME_POLICY, + LifetimePolicy.PERMANENT.name(), provider.get(GroupProvider.LIFETIME_POLICY)); + assertEquals("Unexpected value of provider attribute " + GroupProvider.DURABLE, Boolean.TRUE, + provider.get(GroupProvider.DURABLE)); + assertEquals("Unexpected value of provider attribute " + GroupProvider.TYPE, type, + provider.get(GroupProvider.TYPE)); + + final String name = (String) provider.get(GroupProvider.NAME); + assertEquals("Unexpected value of provider attribute " + GroupProvider.NAME, type, + name); + + @SuppressWarnings("unchecked") + List<Map<String, Object>> groups = (List<Map<String, Object>>) provider.get("groups"); + assertNotNull("Groups were not found", groups); + assertEquals("Unexpected number of groups", 1, groups.size()); + for (Map<String, Object> group : groups) + { + + final String groupName = (String) group.get(Group.NAME); + assertNotNull("Attribute " + Group.NAME, groupName); + + assertNotNull("Attribute " + Group.ID, group.get(Group.ID)); + assertEquals("Attribute " + Group.ID, UUIDGenerator.generateGroupUUID(name, groupName).toString(), group.get(Group.ID)); + } + } + + private File createTemporaryGroupFile() throws Exception + { + File groupFile = File.createTempFile("group", "grp"); + groupFile.deleteOnExit(); + + Properties props = new Properties(); + props.put("myGroup.users", "guest"); + + props.store(new FileOutputStream(groupFile), "test group file"); + + return groupFile; + } +} diff --git a/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/GroupRestTest.java b/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/GroupRestTest.java new file mode 100644 index 0000000000..5430cce6dc --- /dev/null +++ b/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/GroupRestTest.java @@ -0,0 +1,109 @@ +/* + * + * 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.management.plugin.servlet.rest; + +import java.io.File; +import java.io.FileOutputStream; +import java.util.List; +import java.util.Map; +import java.util.Properties; + +import org.apache.qpid.server.model.GroupMember; + +public class GroupRestTest extends QpidRestTestCase +{ + private static final String GROUP_NAME = "myGroup"; + private static final String FILE_GROUP_MANAGER = "FileGroupManager"; + private static final String EXISTING_MEMBER = "user1"; + private static final String NEW_MEMBER = "user2"; + + private File _groupFile; + + @Override + public void setUp() throws Exception + { + _groupFile = createTemporaryGroupFile(); + + setConfigurationProperty("security.file-group-manager.attributes.attribute.name", "groupFile"); + setConfigurationProperty("security.file-group-manager.attributes.attribute.value", _groupFile.getAbsolutePath()); + + super.setUp(); + } + + @Override + public void tearDown() throws Exception + { + super.tearDown(); + + if (_groupFile != null) + { + if (_groupFile.exists()) + { + _groupFile.delete(); + } + } + } + + public void testGet() throws Exception + { + Map<String, Object> group = getRestTestHelper().getJsonAsSingletonList("/rest/group/FileGroupManager/myGroup"); + List<Map<String, Object>> groupmembers = (List<Map<String, Object>>) group.get("groupmembers"); + assertEquals(1, groupmembers.size()); + + Map<String, Object> member1 = groupmembers.get(0); + assertEquals(EXISTING_MEMBER, (String)member1.get(GroupMember.NAME)); + } + + public void testCreateNewMemberOfGroup() throws Exception + { + Map<String, Object> group = getRestTestHelper().getJsonAsSingletonList("/rest/group/FileGroupManager/myGroup"); + getRestTestHelper().assertNumberOfGroupMembers(group, 1); + + getRestTestHelper().createNewGroupMember(FILE_GROUP_MANAGER, GROUP_NAME, NEW_MEMBER); + + group = getRestTestHelper().getJsonAsSingletonList("/rest/group/FileGroupManager/myGroup"); + getRestTestHelper().assertNumberOfGroupMembers(group, 2); + } + + public void testRemoveMemberFromGroup() throws Exception + { + Map<String, Object> group = getRestTestHelper().getJsonAsSingletonList("/rest/group/FileGroupManager/myGroup"); + getRestTestHelper().assertNumberOfGroupMembers(group, 1); + + getRestTestHelper().removeMemberFromGroup(FILE_GROUP_MANAGER, GROUP_NAME, EXISTING_MEMBER); + + group = getRestTestHelper().getJsonAsSingletonList("/rest/group/FileGroupManager/myGroup"); + getRestTestHelper().assertNumberOfGroupMembers(group, 0); + } + + private File createTemporaryGroupFile() throws Exception + { + File groupFile = File.createTempFile("group", "grp"); + groupFile.deleteOnExit(); + + Properties props = new Properties(); + props.put(GROUP_NAME + ".users", EXISTING_MEMBER); + + props.store(new FileOutputStream(groupFile), "test group file"); + + return groupFile; + } +} diff --git a/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/LogRecordsRestTest.java b/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/LogRecordsRestTest.java index c64fd6e1da..34b25e2e40 100644 --- a/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/LogRecordsRestTest.java +++ b/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/LogRecordsRestTest.java @@ -27,10 +27,10 @@ public class LogRecordsRestTest extends QpidRestTestCase { public void testGet() throws Exception { - List<Map<String, Object>> logs = getJsonAsList("/rest/logrecords"); + List<Map<String, Object>> logs = getRestTestHelper().getJsonAsList("/rest/logrecords"); assertNotNull("Logs data cannot be null", logs); assertTrue("Logs are not found", logs.size() > 0); - Map<String, Object> record = find("message", "[Broker] BRK-1004 : Qpid Broker Ready", logs); + Map<String, Object> record = getRestTestHelper().find("message", "[Broker] BRK-1004 : Qpid Broker Ready", logs); assertNotNull("BRK-1004 message is not found", record); assertNotNull("Message id cannot be null", record.get("id")); diff --git a/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/MessagesRestTest.java b/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/MessagesRestTest.java index 492df43957..a4efcc9456 100644 --- a/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/MessagesRestTest.java +++ b/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/MessagesRestTest.java @@ -85,7 +85,7 @@ public class MessagesRestTest extends QpidRestTestCase public void testGet() throws Exception { String queueName = getTestQueueName(); - List<Map<String, Object>> messages = getJsonAsList("/rest/message/test/" + queueName); + List<Map<String, Object>> messages = getRestTestHelper().getJsonAsList("/rest/message/test/" + queueName); assertNotNull("Messages are not found", messages); assertEquals("Unexpected number of messages", MESSAGE_NUMBER, messages.size()); int position = 0; @@ -111,7 +111,7 @@ public class MessagesRestTest extends QpidRestTestCase // get message IDs List<Long> ids = getMesssageIds(queueName); - Map<String, Object> message = getJsonAsMap("/rest/message/test/" + queueName + "/" + ids.get(0)); + Map<String, Object> message = getRestTestHelper().getJsonAsMap("/rest/message/test/" + queueName + "/" + ids.get(0)); assertMessageAttributes(message); assertMessageAttributeValues(message, true); @@ -121,7 +121,7 @@ public class MessagesRestTest extends QpidRestTestCase assertEquals("Unexpected message header", 0, headers.get("index")); Long lastMessageId = ids.get(ids.size() - 1); - message = getJsonAsMap("/rest/message/test/" + queueName + "/" + lastMessageId); + message = getRestTestHelper().getJsonAsMap("/rest/message/test/" + queueName + "/" + lastMessageId); assertMessageAttributes(message); assertEquals("Unexpected message attribute mimeType", "application/octet-stream", message.get("mimeType")); assertEquals("Unexpected message attribute size", 4, message.get("size")); @@ -132,10 +132,10 @@ public class MessagesRestTest extends QpidRestTestCase assertEquals("Unexpected message header", "value", bytesMessageHeader.get("test")); // get content - HttpURLConnection connection = openManagementConection("/rest/message-content/test/" + queueName + "/" + HttpURLConnection connection = getRestTestHelper().openManagementConnection("/rest/message-content/test/" + queueName + "/" + lastMessageId, "GET"); connection.connect(); - byte[] data = readConnectionInputStream(connection); + byte[] data = getRestTestHelper().readConnectionInputStream(connection); assertTrue("Unexpected message", Arrays.equals(messageBytes, data)); } @@ -159,38 +159,38 @@ public class MessagesRestTest extends QpidRestTestCase } // move messages - HttpURLConnection connection = openManagementConection("/rest/message/test/" + queueName, "POST"); + HttpURLConnection connection = getRestTestHelper().openManagementConnection("/rest/message/test/" + queueName, "POST"); Map<String, Object> messagesData = new HashMap<String, Object>(); messagesData.put("messages", movedMessageIds); messagesData.put("destinationQueue", queueName2); messagesData.put("move", Boolean.TRUE); - writeJsonRequest(connection, messagesData); + getRestTestHelper().writeJsonRequest(connection, messagesData); assertEquals("Unexpected response code", 200, connection.getResponseCode()); // check messages on target queue - List<Map<String, Object>> messages = getJsonAsList("/rest/message/test/" + queueName2); + List<Map<String, Object>> messages = getRestTestHelper().getJsonAsList("/rest/message/test/" + queueName2); assertNotNull("Messages are not found", messages); assertEquals("Unexpected number of messages", movedMessageIds.size(), messages.size()); for (Long id : movedMessageIds) { - Map<String, Object> message = find("id", id.intValue(), messages); + Map<String, Object> message = getRestTestHelper().find("id", id.intValue(), messages); assertMessageAttributes(message); } // check messages on original queue - messages = getJsonAsList("/rest/message/test/" + queueName); + messages = getRestTestHelper().getJsonAsList("/rest/message/test/" + queueName); assertNotNull("Messages are not found", messages); assertEquals("Unexpected number of messages", ids.size(), messages.size()); for (Long id : ids) { - Map<String, Object> message = find("id", id.intValue(), messages); + Map<String, Object> message = getRestTestHelper().find("id", id.intValue(), messages); assertMessageAttributes(message); } for (Long id : movedMessageIds) { - Map<String, Object> message = find("id", id.intValue(), messages); + Map<String, Object> message = getRestTestHelper().find("id", id.intValue(), messages); assertNull("Moved message " + id + " is found on original queue", message); } } @@ -214,37 +214,37 @@ public class MessagesRestTest extends QpidRestTestCase } // copy messages - HttpURLConnection connection = openManagementConection("/rest/message/test/" + queueName, "POST"); + HttpURLConnection connection = getRestTestHelper().openManagementConnection("/rest/message/test/" + queueName, "POST"); Map<String, Object> messagesData = new HashMap<String, Object>(); messagesData.put("messages", copyMessageIds); messagesData.put("destinationQueue", queueName2); - writeJsonRequest(connection, messagesData); + getRestTestHelper().writeJsonRequest(connection, messagesData); assertEquals("Unexpected response code", 200, connection.getResponseCode()); // check messages on target queue - List<Map<String, Object>> messages = getJsonAsList("/rest/message/test/" + queueName2); + List<Map<String, Object>> messages = getRestTestHelper().getJsonAsList("/rest/message/test/" + queueName2); assertNotNull("Messages are not found", messages); assertEquals("Unexpected number of messages", copyMessageIds.size(), messages.size()); for (Long id : copyMessageIds) { - Map<String, Object> message = find("id", id.intValue(), messages); + Map<String, Object> message = getRestTestHelper().find("id", id.intValue(), messages); assertMessageAttributes(message); } // check messages on original queue - messages = getJsonAsList("/rest/message/test/" + queueName); + messages = getRestTestHelper().getJsonAsList("/rest/message/test/" + queueName); assertNotNull("Messages are not found", messages); assertEquals("Unexpected number of messages", MESSAGE_NUMBER, messages.size()); for (Long id : ids) { - Map<String, Object> message = find("id", id.intValue(), messages); + Map<String, Object> message = getRestTestHelper().find("id", id.intValue(), messages); assertMessageAttributes(message); } for (Long id : copyMessageIds) { - Map<String, Object> message = find("id", id.intValue(), messages); + Map<String, Object> message = getRestTestHelper().find("id", id.intValue(), messages); assertMessageAttributes(message); } } @@ -272,30 +272,30 @@ public class MessagesRestTest extends QpidRestTestCase } // delete messages - HttpURLConnection connection = openManagementConection( + HttpURLConnection connection = getRestTestHelper().openManagementConnection( "/rest/message/test/" + queueName + "?" + queryString.toString(), "DELETE"); connection.connect(); assertEquals("Unexpected response code", 200, connection.getResponseCode()); // check messages on queue - List<Map<String, Object>> messages = getJsonAsList("/rest/message/test/" + queueName); + List<Map<String, Object>> messages = getRestTestHelper().getJsonAsList("/rest/message/test/" + queueName); assertNotNull("Messages are not found", messages); assertEquals("Unexpected number of messages", ids.size(), messages.size()); for (Long id : ids) { - Map<String, Object> message = find("id", id.intValue(), messages); + Map<String, Object> message = getRestTestHelper().find("id", id.intValue(), messages); assertMessageAttributes(message); } for (Long id : deleteMessageIds) { - Map<String, Object> message = find("id", id.intValue(), messages); + Map<String, Object> message = getRestTestHelper().find("id", id.intValue(), messages); assertNull("Message with id " + id + " was not deleted", message); } } private List<Long> getMesssageIds(String queueName) throws IOException, JsonParseException, JsonMappingException { - List<Map<String, Object>> messages = getJsonAsList("/rest/message/test/" + queueName); + List<Map<String, Object>> messages = getRestTestHelper().getJsonAsList("/rest/message/test/" + queueName); List<Long> ids = new ArrayList<Long>(); for (Map<String, Object> message : messages) { diff --git a/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/PortRestTest.java b/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/PortRestTest.java index 739ef5c737..ea897881a9 100644 --- a/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/PortRestTest.java +++ b/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/PortRestTest.java @@ -30,14 +30,14 @@ public class PortRestTest extends QpidRestTestCase { public void testGet() throws Exception { - List<Map<String, Object>> ports = getJsonAsList("/rest/port/"); + List<Map<String, Object>> ports = getRestTestHelper().getJsonAsList("/rest/port/"); assertNotNull("Port data cannot be null", ports); assertEquals("Unexpected number of ports", 2, ports.size()); - int[] expectedPorts = { getPort(), getHttpPort() }; + int[] expectedPorts = { getPort(), getRestTestHelper().getHttpPort() }; for (int port : expectedPorts) { String portName = "0.0.0.0:" + port; - Map<String, Object> portData = find(Port.NAME, portName, ports); + Map<String, Object> portData = getRestTestHelper().find(Port.NAME, portName, ports); assertNotNull("Port " + portName + " is not found", portData); Asserts.assertPortAttributes(portData); } @@ -45,14 +45,14 @@ public class PortRestTest extends QpidRestTestCase public void testGetPort() throws Exception { - List<Map<String, Object>> ports = getJsonAsList("/rest/port/"); + List<Map<String, Object>> ports = getRestTestHelper().getJsonAsList("/rest/port/"); assertNotNull("Ports data cannot be null", ports); assertEquals("Unexpected number of ports", 2, ports.size()); for (Map<String, Object> portMap : ports) { String portName = (String) portMap.get(Port.NAME); assertNotNull("Port name attribute is not found", portName); - Map<String, Object> portData = getJsonAsSingletonList("/rest/port/" + URLDecoder.decode(portName, "UTF-8")); + Map<String, Object> portData = getRestTestHelper().getJsonAsSingletonList("/rest/port/" + URLDecoder.decode(portName, "UTF-8")); assertNotNull("Port " + portName + " is not found", portData); Asserts.assertPortAttributes(portData); } diff --git a/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/QpidRestTestCase.java b/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/QpidRestTestCase.java index e83341de80..958e68ab70 100644 --- a/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/QpidRestTestCase.java +++ b/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/QpidRestTestCase.java @@ -20,226 +20,50 @@ */ package org.apache.qpid.server.management.plugin.servlet.rest; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; import java.io.IOException; -import java.io.InputStream; -import java.net.HttpURLConnection; -import java.net.InetAddress; -import java.net.MalformedURLException; -import java.net.URL; -import java.util.ArrayList; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; import org.apache.commons.configuration.ConfigurationException; -import org.apache.log4j.Logger; import org.apache.qpid.test.utils.QpidBrokerTestCase; -import org.codehaus.jackson.JsonGenerationException; -import org.codehaus.jackson.JsonParseException; -import org.codehaus.jackson.map.JsonMappingException; -import org.codehaus.jackson.map.ObjectMapper; -import org.codehaus.jackson.type.TypeReference; public class QpidRestTestCase extends QpidBrokerTestCase { - private static final Logger LOGGER = Logger.getLogger(QpidRestTestCase.class); - public static final String[] EXPECTED_HOSTS = { "development", "test", "localhost" }; public static final String[] EXPECTED_QUEUES = { "queue", "ping" }; public static final String[] EXPECTED_EXCHANGES = { "amq.fanout", "amq.match", "amq.direct", "amq.topic", "qpid.management", "<<default>>" }; - private int _httpPort; - private String _hostName; - private List<HttpURLConnection> _httpConnections; + private RestTestHelper _restTestHelper = new RestTestHelper(findFreePort()); @Override public void setUp() throws Exception { - _httpConnections = new ArrayList<HttpURLConnection>(); - _hostName = InetAddress.getLocalHost().getHostName(); - _httpPort = findFreePort(); customizeConfiguration(); super.setUp(); - - } - - protected void customizeConfiguration() throws ConfigurationException, IOException - { - setConfigurationProperty("management.enabled", "false"); - setConfigurationProperty("management.http.enabled", "true"); - setConfigurationProperty("management.https.enabled", "false"); - setConfigurationProperty("management.http.port", Integer.toString(_httpPort)); - } - - public void teearDown() throws Exception - { - for (HttpURLConnection connection : _httpConnections) - { - try - { - connection.disconnect(); - } - catch (Exception e) - { - // ignore - } - } - super.tearDown(); - } - - protected int getHttpPort() - { - return _httpPort; - } - - protected String getHostName() - { - return _hostName; - } - - protected String getProtocol() - { - return "http"; - } - - protected String getManagementURL() - { - return getProtocol() + "://" + getHostName() + ":" + getHttpPort(); - } - - protected URL getManagementURL(String path) throws MalformedURLException - { - return new URL(getManagementURL() + path); - } - - protected HttpURLConnection openManagementConection(String path) throws IOException - { - URL url = getManagementURL(path); - HttpURLConnection httpCon = (HttpURLConnection) url.openConnection(); - httpCon.setDoOutput(true); - return httpCon; - } - - protected HttpURLConnection openManagementConection(String path, String method) throws IOException - { - HttpURLConnection httpCon = openManagementConection(path); - httpCon.setRequestMethod(method); - return httpCon; } - protected List<Map<String, Object>> readJsonResponseAsList(HttpURLConnection connection) throws IOException, - JsonParseException, JsonMappingException - { - byte[] data = readConnectionInputStream(connection); - - ObjectMapper mapper = new ObjectMapper(); - - TypeReference<List<LinkedHashMap<String, Object>>> typeReference = new TypeReference<List<LinkedHashMap<String, Object>>>() - { - }; - List<Map<String, Object>> providedObject = mapper.readValue(new ByteArrayInputStream(data), typeReference); - return providedObject; - } - - protected Map<String, Object> readJsonResponseAsMap(HttpURLConnection connection) throws IOException, - JsonParseException, JsonMappingException - { - byte[] data = readConnectionInputStream(connection); - - ObjectMapper mapper = new ObjectMapper(); - - TypeReference<LinkedHashMap<String, Object>> typeReference = new TypeReference<LinkedHashMap<String, Object>>() - { - }; - Map<String, Object> providedObject = mapper.readValue(new ByteArrayInputStream(data), typeReference); - return providedObject; - } - - protected byte[] readConnectionInputStream(HttpURLConnection connection) throws IOException - { - InputStream is = connection.getInputStream(); - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - byte[] buffer = new byte[1024]; - int len = -1; - while ((len = is.read(buffer)) != -1) - { - baos.write(buffer, 0, len); - } - if (LOGGER.isTraceEnabled()) - { - LOGGER.trace("RESPONSE:" + new String(baos.toByteArray())); - } - return baos.toByteArray(); - } - - protected void writeJsonRequest(HttpURLConnection connection, Map<String, Object> data) throws JsonGenerationException, - JsonMappingException, IOException - { - ObjectMapper mapper = new ObjectMapper(); - mapper.writeValue(connection.getOutputStream(), data); - } - - protected Map<String, Object> find(String name, Object value, List<Map<String, Object>> data) + @Override + protected void tearDown() throws Exception { - for (Map<String, Object> map : data) + try { - Object mapValue = map.get(name); - if (value.equals(mapValue)) - { - return map; - } + super.tearDown(); } - return null; - } - - protected Map<String, Object> find(Map<String, Object> searchAttributes, List<Map<String, Object>> data) - { - for (Map<String, Object> map : data) + finally { - boolean equals = true; - for (Map.Entry<String, Object> entry : searchAttributes.entrySet()) - { - Object mapValue = map.get(entry.getKey()); - if (!entry.getValue().equals(mapValue)) - { - equals = false; - break; - } - } - if (equals) - { - return map; - } + getRestTestHelper().tearDown(); } - return null; } - protected Map<String, Object> getJsonAsSingletonList(String path) throws IOException - { - List<Map<String, Object>> response = getJsonAsList(path); - - assertNotNull("Response cannot be null", response); - assertEquals("Unexpected response", 1, response.size()); - return response.get(0); - } - - protected List<Map<String, Object>> getJsonAsList(String path) throws IOException, JsonParseException, - JsonMappingException + protected void customizeConfiguration() throws ConfigurationException, IOException { - HttpURLConnection connection = openManagementConection(path, "GET"); - connection.connect(); - List<Map<String, Object>> response = readJsonResponseAsList(connection); - return response; + setConfigurationProperty("management.enabled", "false"); + setConfigurationProperty("management.http.enabled", "true"); + setConfigurationProperty("management.https.enabled", "false"); + setConfigurationProperty("management.http.port", Integer.toString(_restTestHelper.getHttpPort())); } - protected Map<String, Object> getJsonAsMap(String path) throws IOException + public RestTestHelper getRestTestHelper() { - HttpURLConnection connection = openManagementConection(path, "GET"); - connection.connect(); - Map<String, Object> response = readJsonResponseAsMap(connection); - return response; + return _restTestHelper; } } diff --git a/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/QueueRestTest.java b/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/QueueRestTest.java index 5f11b3fb1d..d7732af688 100644 --- a/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/QueueRestTest.java +++ b/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/QueueRestTest.java @@ -80,7 +80,7 @@ public class QueueRestTest extends QpidRestTestCase public void testGetVirtualHostQueues() throws Exception { String queueName = getTestQueueName(); - List<Map<String, Object>> queues = getJsonAsList("/rest/queue/test"); + List<Map<String, Object>> queues = getRestTestHelper().getJsonAsList("/rest/queue/test"); assertEquals("Unexpected number of queues", EXPECTED_QUEUES.length + 1, queues.size()); String[] expectedQueues = new String[EXPECTED_QUEUES.length + 1]; System.arraycopy(EXPECTED_QUEUES, 0, expectedQueues, 0, EXPECTED_QUEUES.length); @@ -88,7 +88,7 @@ public class QueueRestTest extends QpidRestTestCase for (String name : expectedQueues) { - Map<String, Object> queueDetails = find(Queue.NAME, name, queues); + Map<String, Object> queueDetails = getRestTestHelper().find(Queue.NAME, name, queues); Asserts.assertQueue(name, "standard", queueDetails); @SuppressWarnings("unchecked") @@ -96,8 +96,8 @@ public class QueueRestTest extends QpidRestTestCase assertNotNull("Queue bindings are not found", bindings); assertEquals("Unexpected number of bindings", 2, bindings.size()); - Map<String, Object> defaultExchangeBinding = find(Binding.EXCHANGE, "<<default>>", bindings); - Map<String, Object> directExchangeBinding = find(Binding.EXCHANGE, "amq.direct", bindings); + Map<String, Object> defaultExchangeBinding = getRestTestHelper().find(Binding.EXCHANGE, "<<default>>", bindings); + Map<String, Object> directExchangeBinding = getRestTestHelper().find(Binding.EXCHANGE, "amq.direct", bindings); Asserts.assertBinding(name, "<<default>>", defaultExchangeBinding); Asserts.assertBinding(name, "amq.direct", directExchangeBinding); } @@ -106,7 +106,7 @@ public class QueueRestTest extends QpidRestTestCase public void testGetByName() throws Exception { String queueName = getTestQueueName(); - Map<String, Object> queueDetails = getJsonAsSingletonList("/rest/queue/test/" + queueName); + Map<String, Object> queueDetails = getRestTestHelper().getJsonAsSingletonList("/rest/queue/test/" + queueName); Asserts.assertQueue(queueName, "standard", queueDetails); assertStatistics(queueDetails); @@ -115,8 +115,8 @@ public class QueueRestTest extends QpidRestTestCase assertNotNull("Queue bindings are not found", bindings); assertEquals("Unexpected number of bindings", 2, bindings.size()); - Map<String, Object> defaultExchangeBinding = find(Binding.EXCHANGE, "<<default>>", bindings); - Map<String, Object> directExchangeBinding = find(Binding.EXCHANGE, "amq.direct", bindings); + Map<String, Object> defaultExchangeBinding = getRestTestHelper().find(Binding.EXCHANGE, "<<default>>", bindings); + Map<String, Object> directExchangeBinding = getRestTestHelper().find(Binding.EXCHANGE, "amq.direct", bindings); Asserts.assertBinding(queueName, "<<default>>", defaultExchangeBinding); Asserts.assertBinding(queueName, "amq.direct", directExchangeBinding); @@ -138,7 +138,7 @@ public class QueueRestTest extends QpidRestTestCase createBinding(bindingName, exchanges[i], queueName); } - Map<String, Object> queueDetails = getJsonAsSingletonList("/rest/queue/test/" + queueName); + Map<String, Object> queueDetails = getRestTestHelper().getJsonAsSingletonList("/rest/queue/test/" + queueName); Asserts.assertQueue(queueName, "standard", queueDetails); @SuppressWarnings("unchecked") @@ -152,14 +152,14 @@ public class QueueRestTest extends QpidRestTestCase for (int i = 0; i < exchanges.length; i++) { searchAttributes.put(Binding.EXCHANGE, exchanges[i]); - Map<String, Object> binding = find(searchAttributes, bindings); + Map<String, Object> binding = getRestTestHelper().find(searchAttributes, bindings); Asserts.assertBinding(bindingName, queueName, exchanges[i], binding); } } private void createBinding(String bindingName, String exchangeName, String queueName) throws IOException { - HttpURLConnection connection = openManagementConection( + HttpURLConnection connection = getRestTestHelper().openManagementConnection( "/rest/binding/test/" + URLDecoder.decode(exchangeName, "UTF-8") + "/" + queueName + "/" + bindingName, "PUT"); @@ -168,7 +168,7 @@ public class QueueRestTest extends QpidRestTestCase bindingData.put(Binding.EXCHANGE, exchangeName); bindingData.put(Binding.QUEUE, queueName); - writeJsonRequest(connection, bindingData); + getRestTestHelper().writeJsonRequest(connection, bindingData); assertEquals("Unexpected response code", 201, connection.getResponseCode()); connection.disconnect(); diff --git a/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/RestTestHelper.java b/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/RestTestHelper.java new file mode 100644 index 0000000000..8a323c0639 --- /dev/null +++ b/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/RestTestHelper.java @@ -0,0 +1,417 @@ +/* + * 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.management.plugin.servlet.rest; + +import java.io.BufferedWriter; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.io.InputStream; +import java.net.HttpURLConnection; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLDecoder; +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.SSLSocketFactory; +import javax.servlet.http.HttpServletResponse; + +import junit.framework.Assert; + +import org.apache.commons.codec.binary.Base64; +import org.apache.commons.configuration.ConfigurationException; +import org.apache.log4j.Logger; +import org.apache.qpid.test.utils.QpidBrokerTestCase; +import org.codehaus.jackson.JsonGenerationException; +import org.codehaus.jackson.JsonParseException; +import org.codehaus.jackson.map.JsonMappingException; +import org.codehaus.jackson.map.ObjectMapper; +import org.codehaus.jackson.type.TypeReference; + +public class RestTestHelper +{ + private static final Logger LOGGER = Logger.getLogger(RestTestHelper.class); + + private int _httpPort; + + private boolean _useSsl; + + private String _username; + + private String _password; + + private File _passwdFile; + + public RestTestHelper(int httpPort) + { + _httpPort = httpPort; + } + + public int getHttpPort() + { + return _httpPort; + } + + private String getHostName() + { + return "localhost"; + } + + private String getProtocol() + { + return _useSsl ? "https" : "http"; + } + + public String getManagementURL() + { + return getProtocol() + "://" + getHostName() + ":" + getHttpPort(); + } + + public URL getManagementURL(String path) throws MalformedURLException + { + return new URL(getManagementURL() + path); + } + + public HttpURLConnection openManagementConnection(String path, String method) throws IOException + { + URL url = getManagementURL(path); + HttpURLConnection httpCon = (HttpURLConnection) url.openConnection(); + if(_useSsl) + { + ((HttpsURLConnection) httpCon).setSSLSocketFactory((SSLSocketFactory) SSLSocketFactory.getDefault()); + } + if(_username != null) + { + String encoded = new String(new Base64().encode((_username + ":" + _password).getBytes())); + httpCon.setRequestProperty("Authorization", "Basic " + encoded); + } + httpCon.setDoOutput(true); + httpCon.setRequestMethod(method); + return httpCon; + } + + public List<Map<String, Object>> readJsonResponseAsList(HttpURLConnection connection) throws IOException, + JsonParseException, JsonMappingException + { + byte[] data = readConnectionInputStream(connection); + + ObjectMapper mapper = new ObjectMapper(); + + TypeReference<List<LinkedHashMap<String, Object>>> typeReference = new TypeReference<List<LinkedHashMap<String, Object>>>() + { + }; + List<Map<String, Object>> providedObject = mapper.readValue(new ByteArrayInputStream(data), typeReference); + return providedObject; + } + + public Map<String, Object> readJsonResponseAsMap(HttpURLConnection connection) throws IOException, + JsonParseException, JsonMappingException + { + byte[] data = readConnectionInputStream(connection); + + ObjectMapper mapper = new ObjectMapper(); + + TypeReference<LinkedHashMap<String, Object>> typeReference = new TypeReference<LinkedHashMap<String, Object>>() + { + }; + Map<String, Object> providedObject = mapper.readValue(new ByteArrayInputStream(data), typeReference); + return providedObject; + } + + public byte[] readConnectionInputStream(HttpURLConnection connection) throws IOException + { + InputStream is = connection.getInputStream(); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + byte[] buffer = new byte[1024]; + int len = -1; + while ((len = is.read(buffer)) != -1) + { + baos.write(buffer, 0, len); + } + if (LOGGER.isTraceEnabled()) + { + LOGGER.trace("RESPONSE:" + new String(baos.toByteArray())); + } + return baos.toByteArray(); + } + + public void writeJsonRequest(HttpURLConnection connection, Map<String, Object> data) throws JsonGenerationException, + JsonMappingException, IOException + { + ObjectMapper mapper = new ObjectMapper(); + mapper.writeValue(connection.getOutputStream(), data); + } + + public Map<String, Object> find(String name, Object value, List<Map<String, Object>> data) + { + for (Map<String, Object> map : data) + { + Object mapValue = map.get(name); + if (value.equals(mapValue)) + { + return map; + } + } + return null; + } + + public Map<String, Object> find(Map<String, Object> searchAttributes, List<Map<String, Object>> data) + { + for (Map<String, Object> map : data) + { + boolean equals = true; + for (Map.Entry<String, Object> entry : searchAttributes.entrySet()) + { + Object mapValue = map.get(entry.getKey()); + if (!entry.getValue().equals(mapValue)) + { + equals = false; + break; + } + } + if (equals) + { + return map; + } + } + return null; + } + + public Map<String, Object> getJsonAsSingletonList(String path) throws IOException + { + List<Map<String, Object>> response = getJsonAsList(path); + + Assert.assertNotNull("Response cannot be null", response); + Assert.assertEquals("Unexpected response", 1, response.size()); + return response.get(0); + } + + public List<Map<String, Object>> getJsonAsList(String path) throws IOException, JsonParseException, + JsonMappingException + { + HttpURLConnection connection = openManagementConnection(path, "GET"); + connection.connect(); + List<Map<String, Object>> response = readJsonResponseAsList(connection); + return response; + } + + public Map<String, Object> getJsonAsMap(String path) throws IOException + { + HttpURLConnection connection = openManagementConnection(path, "GET"); + connection.connect(); + Map<String, Object> response = readJsonResponseAsMap(connection); + return response; + } + + public void createNewGroupMember(String groupProviderName, String groupName, String memberName, int responseCode) throws IOException + { + HttpURLConnection connection = openManagementConnection( + "/rest/groupmember/" + URLDecoder.decode(groupProviderName, "UTF-8") + "/"+ URLDecoder.decode(groupName, "UTF-8") + "/" + URLDecoder.decode(memberName, "UTF-8"), + "PUT"); + + Map<String, Object> groupMemberData = new HashMap<String, Object>(); + // TODO add type + writeJsonRequest(connection, groupMemberData); + + Assert.assertEquals("Unexpected response code", responseCode, connection.getResponseCode()); + + connection.disconnect(); + } + + public void createNewGroupMember(String groupProviderName, String groupName, String memberName) throws IOException + { + createNewGroupMember(groupProviderName, groupName, memberName, HttpServletResponse.SC_CREATED); + } + + public void removeMemberFromGroup(String groupProviderName, String groupName, String memberName, int responseCode) throws IOException + { + HttpURLConnection connection = openManagementConnection( + "/rest/groupmember/" + URLDecoder.decode(groupProviderName, "UTF-8") + "/"+ URLDecoder.decode(groupName, "UTF-8") + "/" + URLDecoder.decode(memberName, "UTF-8"), + "DELETE"); + + Assert.assertEquals("Unexpected response code", responseCode, connection.getResponseCode()); + + connection.disconnect(); + } + + public void removeMemberFromGroup(String groupProviderName, String groupName, String memberName) throws IOException + { + removeMemberFromGroup(groupProviderName, groupName, memberName, HttpServletResponse.SC_OK); + } + + public void assertNumberOfGroupMembers(Map<String, Object> data, int expectedNumberOfGroupMembers) + { + List<Map<String, Object>> groups = (List<Map<String, Object>>) data.get("groupmembers"); + if (groups == null) + { + groups = Collections.emptyList(); + } + + Assert.assertEquals("Unexpected number of group members", expectedNumberOfGroupMembers, groups.size()); + } + + public void createGroup(String groupName, String groupProviderName) throws IOException + { + createGroup(groupName, groupProviderName, HttpServletResponse.SC_CREATED); + } + + public void createGroup(String groupName, String groupProviderName, int responseCode) throws IOException + { + HttpURLConnection connection = openManagementConnection( + "/rest/group/" + URLDecoder.decode(groupProviderName, "UTF-8") + "/"+ URLDecoder.decode(groupName, "UTF-8"), + "PUT"); + + Map<String, Object> groupData = new HashMap<String, Object>(); + writeJsonRequest(connection, groupData); + + Assert.assertEquals("Unexpected response code", responseCode, connection.getResponseCode()); + + connection.disconnect(); + } + + public void createOrUpdateUser(String username, String password) throws IOException + { + createOrUpdateUser(username, password, HttpServletResponse.SC_CREATED); + } + + public void createOrUpdateUser(String username, String password, int responseCode) throws IOException + { + HttpURLConnection connection = openManagementConnection("/rest/user/PrincipalDatabaseAuthenticationManager/" + username, "PUT"); + + Map<String, Object> data = new HashMap<String, Object>(); + data.put("password", password); + writeJsonRequest(connection, data); + + Assert.assertEquals("Unexpected response code", responseCode, connection.getResponseCode()); + + connection.disconnect(); + } + + public void removeGroup(String groupName, String groupProviderName, int responseCode) throws IOException + { + HttpURLConnection connection = openManagementConnection( + "/rest/group/" + URLDecoder.decode(groupProviderName, "UTF-8") + "/"+ URLDecoder.decode(groupName, "UTF-8"), + "DELETE"); + + Assert.assertEquals("Unexpected response code", responseCode, connection.getResponseCode()); + connection.disconnect(); + } + + public void removeGroup(String groupName, String groupProviderName) throws IOException + { + removeGroup(groupName, groupProviderName, HttpServletResponse.SC_OK); + } + + public void removeUserById(String id) throws IOException + { + HttpURLConnection connection = openManagementConnection("/rest/user/PrincipalDatabaseAuthenticationManager?id=" + id, "DELETE"); + Assert.assertEquals("Unexpected response code", HttpServletResponse.SC_OK, connection.getResponseCode()); + connection.disconnect(); + } + + public void removeUser(String username, int responseCode) throws IOException + { + HttpURLConnection connection = openManagementConnection("/rest/user/PrincipalDatabaseAuthenticationManager/" + username, "DELETE"); + Assert.assertEquals("Unexpected response code", responseCode, connection.getResponseCode()); + connection.disconnect(); + } + + public void removeUser(String username) throws IOException + { + removeUser(username, HttpServletResponse.SC_OK); + } + + public void assertNumberOfGroups(Map<String, Object> data, int expectedNumberOfGroups) + { + List<Map<String, Object>> groups = (List<Map<String, Object>>) data.get("groups"); + if (groups == null) + { + groups = Collections.emptyList(); + } + Assert.assertEquals("Unexpected number of groups", expectedNumberOfGroups, groups.size()); + } + + public void setUseSsl(boolean useSsl) + { + _useSsl = useSsl; + } + + public void setUsernameAndPassword(String username, String password) + { + _username = username; + _password = password; + } + + /** + * Create password file that follows the convention username=password, which is deleted by {@link #tearDown()} + */ + public void configureTemporaryPasswordFile(QpidBrokerTestCase testCase, String... users) throws ConfigurationException, IOException + { + _passwdFile = createTemporaryPasswdFile(users); + + testCase.setConfigurationProperty("security.pd-auth-manager.principal-database.attributes.attribute.name", "passwordFile"); + testCase.setConfigurationProperty("security.pd-auth-manager.principal-database.attributes.attribute.value", _passwdFile.getAbsolutePath()); + } + + public void tearDown() + { + if (_passwdFile != null) + { + if (_passwdFile.exists()) + { + _passwdFile.delete(); + } + } + } + + private File createTemporaryPasswdFile(String[] users) throws IOException + { + BufferedWriter writer = null; + try + { + File testFile = File.createTempFile(this.getClass().getName(),"tmp"); + testFile.deleteOnExit(); + + writer = new BufferedWriter(new FileWriter(testFile)); + for (int i = 0; i < users.length; i++) + { + String username = users[i]; + writer.write(username + ":" + username); + writer.newLine(); + } + + return testFile; + + } + finally + { + if (writer != null) + { + writer.close(); + } + } + } +} diff --git a/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/SaslRestTest.java b/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/SaslRestTest.java index b504c9fa60..d65b06e6a6 100644 --- a/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/SaslRestTest.java +++ b/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/SaslRestTest.java @@ -27,7 +27,7 @@ public class SaslRestTest extends QpidRestTestCase { public void testGet() throws Exception { - Map<String, Object> saslData = getJsonAsMap("/rest/sasl"); + Map<String, Object> saslData = getRestTestHelper().getJsonAsMap("/rest/sasl"); assertNotNull("mechanisms attribute is not found", saslData.get("mechanisms")); @SuppressWarnings("unchecked") diff --git a/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/StructureRestTest.java b/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/StructureRestTest.java index b01e1d44b8..c72dcfc8ab 100644 --- a/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/StructureRestTest.java +++ b/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/StructureRestTest.java @@ -28,7 +28,7 @@ public class StructureRestTest extends QpidRestTestCase public void testGet() throws Exception { - Map<String, Object> structure = getJsonAsMap("/rest/structure"); + Map<String, Object> structure = getRestTestHelper().getJsonAsMap("/rest/structure"); assertNotNull("Structure data cannot be null", structure); assertNode(structure, "Broker"); @@ -46,7 +46,7 @@ public class StructureRestTest extends QpidRestTestCase for (String hostName : EXPECTED_HOSTS) { - Map<String, Object> host = find("name", hostName, virtualhosts); + Map<String, Object> host = getRestTestHelper().find("name", hostName, virtualhosts); assertNotNull("Host " + hostName + " is not found ", host); assertNode(host, hostName); @@ -55,7 +55,7 @@ public class StructureRestTest extends QpidRestTestCase assertNotNull("Host " + hostName + " queues are not found ", queues); for (String queueName : EXPECTED_QUEUES) { - Map<String, Object> queue = find("name", queueName, queues); + Map<String, Object> queue = getRestTestHelper().find("name", queueName, queues); assertNotNull(hostName + " queue " + queueName + " is not found ", queue); assertNode(queue, queueName); @@ -73,7 +73,7 @@ public class StructureRestTest extends QpidRestTestCase assertNotNull("Host " + hostName + " exchanges are not found ", exchanges); for (String exchangeName : EXPECTED_EXCHANGES) { - Map<String, Object> exchange = find("name", exchangeName, exchanges); + Map<String, Object> exchange = getRestTestHelper().find("name", exchangeName, exchanges); assertNotNull("Exchange " + exchangeName + " is not found ", exchange); assertNode(exchange, exchangeName); if ("amq.direct".equalsIgnoreCase(exchangeName) || "<<default>>".equalsIgnoreCase(exchangeName)) @@ -83,7 +83,7 @@ public class StructureRestTest extends QpidRestTestCase assertNotNull(hostName + " exchange " + exchangeName + " bindings are not found ", bindings); for (String queueName : EXPECTED_QUEUES) { - Map<String, Object> binding = find("name", queueName, bindings); + Map<String, Object> binding = getRestTestHelper().find("name", queueName, bindings); assertNotNull(hostName + " exchange " + exchangeName + " binding " + queueName + " is not found", binding); assertNode(binding, queueName); } @@ -97,11 +97,11 @@ public class StructureRestTest extends QpidRestTestCase assertNode(aliases.get(0), hostName); } - int[] expectedPorts = { getPort(), getHttpPort() }; + int[] expectedPorts = { getPort(), getRestTestHelper().getHttpPort() }; for (int port : expectedPorts) { String portName = "0.0.0.0:" + port; - Map<String, Object> portData = find("name", portName, ports); + Map<String, Object> portData = getRestTestHelper().find("name", portName, ports); assertNotNull("Port " + portName + " is not found ", portData); assertNode(portData, portName); } diff --git a/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/UserRestTest.java b/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/UserRestTest.java index e56fa27e21..037d26a7bd 100644 --- a/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/UserRestTest.java +++ b/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/UserRestTest.java @@ -20,8 +20,6 @@ */ package org.apache.qpid.server.management.plugin.servlet.rest; -import java.net.HttpURLConnection; -import java.util.HashMap; import java.util.List; import java.util.Map; @@ -29,9 +27,17 @@ import org.apache.qpid.server.model.User; public class UserRestTest extends QpidRestTestCase { + @Override + public void setUp() throws Exception + { + getRestTestHelper().configureTemporaryPasswordFile(this, "user1", "user2"); + + super.setUp(); // do this last because it starts the broker, using the modified config + } + public void testGet() throws Exception { - List<Map<String, Object>> users = getJsonAsList("/rest/user"); + List<Map<String, Object>> users = getRestTestHelper().getJsonAsList("/rest/user"); assertNotNull("Users cannot be null", users); assertTrue("Unexpected number of users", users.size() > 1); for (Map<String, Object> user : users) @@ -42,7 +48,7 @@ public class UserRestTest extends QpidRestTestCase public void testGetUserByName() throws Exception { - List<Map<String, Object>> users = getJsonAsList("/rest/user"); + List<Map<String, Object>> users = getRestTestHelper().getJsonAsList("/rest/user"); assertNotNull("Users cannot be null", users); assertTrue("Unexpected number of users", users.size() > 1); for (Map<String, Object> user : users) @@ -50,7 +56,7 @@ public class UserRestTest extends QpidRestTestCase assertNotNull("Attribute " + User.ID, user.get(User.ID)); String userName = (String) user.get(User.NAME); assertNotNull("Attribute " + User.NAME, userName); - Map<String, Object> userDetails = getJsonAsSingletonList("/rest/user/PrincipalDatabaseAuthenticationManager/" + Map<String, Object> userDetails = getRestTestHelper().getJsonAsSingletonList("/rest/user/PrincipalDatabaseAuthenticationManager/" + userName); assertUser(userDetails); assertEquals("Unexpected user name", userName, userDetails.get(User.NAME)); @@ -60,19 +66,9 @@ public class UserRestTest extends QpidRestTestCase public void testPut() throws Exception { String userName = getTestName(); - HttpURLConnection connection = openManagementConection("/rest/user/PrincipalDatabaseAuthenticationManager/" - + userName, "PUT"); - - Map<String, Object> userData = new HashMap<String, Object>(); - userData.put(User.NAME, userName); - userData.put(User.PASSWORD, userName); + getRestTestHelper().createOrUpdateUser(userName, "newPassword"); - writeJsonRequest(connection, userData); - assertEquals("Unexpected response code", 201, connection.getResponseCode()); - - connection.disconnect(); - - Map<String, Object> userDetails = getJsonAsSingletonList("/rest/user/PrincipalDatabaseAuthenticationManager/" + Map<String, Object> userDetails = getRestTestHelper().getJsonAsSingletonList("/rest/user/PrincipalDatabaseAuthenticationManager/" + userName); assertUser(userDetails); assertEquals("Unexpected user name", userName, userDetails.get(User.NAME)); @@ -80,27 +76,16 @@ public class UserRestTest extends QpidRestTestCase public void testDelete() throws Exception { - // add user String userName = getTestName(); - HttpURLConnection connection = openManagementConection("/rest/user/PrincipalDatabaseAuthenticationManager/" - + userName, "PUT"); - - Map<String, Object> userData = new HashMap<String, Object>(); - userData.put(User.NAME, userName); - userData.put(User.PASSWORD, userName); + getRestTestHelper().createOrUpdateUser(userName, "newPassword"); - writeJsonRequest(connection, userData); - assertEquals("Unexpected response code", 201, connection.getResponseCode()); - connection.disconnect(); - - Map<String, Object> userDetails = getJsonAsSingletonList("/rest/user/PrincipalDatabaseAuthenticationManager/" + Map<String, Object> userDetails = getRestTestHelper().getJsonAsSingletonList("/rest/user/PrincipalDatabaseAuthenticationManager/" + userName); String id = (String) userDetails.get(User.ID); - connection = openManagementConection("/rest/user/PrincipalDatabaseAuthenticationManager?id=" + id, "DELETE"); - connection.connect(); - assertEquals("Unexpected response code", 200, connection.getResponseCode()); - List<Map<String, Object>> users = getJsonAsList("/rest/user/PrincipalDatabaseAuthenticationManager/" + userName); + getRestTestHelper().removeUserById(id); + + List<Map<String, Object>> users = getRestTestHelper().getJsonAsList("/rest/user/PrincipalDatabaseAuthenticationManager/" + userName); assertEquals("User should be deleted", 0, users.size()); } diff --git a/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/VirtualHostRestTest.java b/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/VirtualHostRestTest.java index 17f1aaaf7b..4bd936a948 100644 --- a/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/VirtualHostRestTest.java +++ b/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/VirtualHostRestTest.java @@ -46,12 +46,12 @@ public class VirtualHostRestTest extends QpidRestTestCase public void testGet() throws Exception { - List<Map<String, Object>> hosts = getJsonAsList("/rest/virtualhost/"); + List<Map<String, Object>> hosts = getRestTestHelper().getJsonAsList("/rest/virtualhost/"); assertNotNull("Hosts data cannot be null", hosts); assertEquals("Unexpected number of hosts", 3, hosts.size()); for (String hostName : EXPECTED_HOSTS) { - Map<String, Object> host = find("name", hostName, hosts); + Map<String, Object> host = getRestTestHelper().find("name", hostName, hosts); Asserts.assertVirtualHost(hostName, host); } } @@ -62,7 +62,7 @@ public class VirtualHostRestTest extends QpidRestTestCase _connection = (AMQConnection) getConnection(); _connection.createSession(true, Session.SESSION_TRANSACTED); - Map<String, Object> hostDetails = getJsonAsSingletonList("/rest/virtualhost/test"); + Map<String, Object> hostDetails = getRestTestHelper().getJsonAsSingletonList("/rest/virtualhost/test"); Asserts.assertVirtualHost("test", hostDetails); @SuppressWarnings("unchecked") @@ -74,18 +74,18 @@ public class VirtualHostRestTest extends QpidRestTestCase @SuppressWarnings("unchecked") List<Map<String, Object>> exchanges = (List<Map<String, Object>>) hostDetails.get(VIRTUALHOST_EXCHANGES_ATTRIBUTE); assertEquals("Unexpected number of exchanges", 6, exchanges.size()); - Asserts.assertDurableExchange("amq.fanout", "fanout", find(Exchange.NAME, "amq.fanout", exchanges)); - Asserts.assertDurableExchange("qpid.management", "management", find(Exchange.NAME, "qpid.management", exchanges)); - Asserts.assertDurableExchange("amq.topic", "topic", find(Exchange.NAME, "amq.topic", exchanges)); - Asserts.assertDurableExchange("amq.direct", "direct", find(Exchange.NAME, "amq.direct", exchanges)); - Asserts.assertDurableExchange("amq.match", "headers", find(Exchange.NAME, "amq.match", exchanges)); - Asserts.assertDurableExchange("<<default>>", "direct", find(Exchange.NAME, "<<default>>", exchanges)); + Asserts.assertDurableExchange("amq.fanout", "fanout", getRestTestHelper().find(Exchange.NAME, "amq.fanout", exchanges)); + Asserts.assertDurableExchange("qpid.management", "management", getRestTestHelper().find(Exchange.NAME, "qpid.management", exchanges)); + Asserts.assertDurableExchange("amq.topic", "topic", getRestTestHelper().find(Exchange.NAME, "amq.topic", exchanges)); + Asserts.assertDurableExchange("amq.direct", "direct", getRestTestHelper().find(Exchange.NAME, "amq.direct", exchanges)); + Asserts.assertDurableExchange("amq.match", "headers", getRestTestHelper().find(Exchange.NAME, "amq.match", exchanges)); + Asserts.assertDurableExchange("<<default>>", "direct", getRestTestHelper().find(Exchange.NAME, "<<default>>", exchanges)); @SuppressWarnings("unchecked") List<Map<String, Object>> queues = (List<Map<String, Object>>) hostDetails.get(VIRTUALHOST_QUEUES_ATTRIBUTE); assertEquals("Unexpected number of queues", 2, queues.size()); - Map<String, Object> queue = find(Queue.NAME, "queue", queues); - Map<String, Object> ping = find(Queue.NAME, "ping", queues); + Map<String, Object> queue = getRestTestHelper().find(Queue.NAME, "queue", queues); + Map<String, Object> ping = getRestTestHelper().find(Queue.NAME, "ping", queues); Asserts.assertQueue("queue", "standard", queue); Asserts.assertQueue("ping", "standard", ping); assertEquals("Unexpected value of queue attribute " + Queue.DURABLE, Boolean.FALSE, queue.get(Queue.DURABLE)); @@ -116,14 +116,14 @@ public class VirtualHostRestTest extends QpidRestTestCase lvqQueueAttributes.put(Queue.LVQ_KEY, "LVQ"); createQueue(queueName + "-lvq", "lvq", lvqQueueAttributes); - Map<String, Object> hostDetails = getJsonAsSingletonList("/rest/virtualhost/test"); + Map<String, Object> hostDetails = getRestTestHelper().getJsonAsSingletonList("/rest/virtualhost/test"); @SuppressWarnings("unchecked") List<Map<String, Object>> queues = (List<Map<String, Object>>) hostDetails.get(VirtualHostRestTest.VIRTUALHOST_QUEUES_ATTRIBUTE); - Map<String, Object> standardQueue = find(Queue.NAME, queueName + "-standard" , queues); - Map<String, Object> sortedQueue = find(Queue.NAME, queueName + "-sorted" , queues); - Map<String, Object> priorityQueue = find(Queue.NAME, queueName + "-priority" , queues); - Map<String, Object> lvqQueue = find(Queue.NAME, queueName + "-lvq" , queues); + Map<String, Object> standardQueue = getRestTestHelper().find(Queue.NAME, queueName + "-standard" , queues); + Map<String, Object> sortedQueue = getRestTestHelper().find(Queue.NAME, queueName + "-sorted" , queues); + Map<String, Object> priorityQueue = getRestTestHelper().find(Queue.NAME, queueName + "-priority" , queues); + Map<String, Object> lvqQueue = getRestTestHelper().find(Queue.NAME, queueName + "-lvq" , queues); Asserts.assertQueue(queueName + "-standard", "standard", standardQueue); Asserts.assertQueue(queueName + "-sorted", "sorted", sortedQueue); @@ -149,14 +149,14 @@ public class VirtualHostRestTest extends QpidRestTestCase createExchange(exchangeName + "-headers", "headers"); createExchange(exchangeName + "-fanout", "fanout"); - Map<String, Object> hostDetails = getJsonAsSingletonList("/rest/virtualhost/test"); + Map<String, Object> hostDetails = getRestTestHelper().getJsonAsSingletonList("/rest/virtualhost/test"); @SuppressWarnings("unchecked") List<Map<String, Object>> exchanges = (List<Map<String, Object>>) hostDetails.get(VirtualHostRestTest.VIRTUALHOST_EXCHANGES_ATTRIBUTE); - Map<String, Object> directExchange = find(Queue.NAME, exchangeName + "-direct" , exchanges); - Map<String, Object> topicExchange = find(Queue.NAME, exchangeName + "-topic" , exchanges); - Map<String, Object> headersExchange = find(Queue.NAME, exchangeName + "-headers" , exchanges); - Map<String, Object> fanoutExchange = find(Queue.NAME, exchangeName + "-fanout" , exchanges); + Map<String, Object> directExchange = getRestTestHelper().find(Queue.NAME, exchangeName + "-direct" , exchanges); + Map<String, Object> topicExchange = getRestTestHelper().find(Queue.NAME, exchangeName + "-topic" , exchanges); + Map<String, Object> headersExchange = getRestTestHelper().find(Queue.NAME, exchangeName + "-headers" , exchanges); + Map<String, Object> fanoutExchange = getRestTestHelper().find(Queue.NAME, exchangeName + "-fanout" , exchanges); Asserts.assertDurableExchange(exchangeName + "-direct", "direct", directExchange); Asserts.assertDurableExchange(exchangeName + "-topic", "topic", topicExchange); @@ -175,11 +175,11 @@ public class VirtualHostRestTest extends QpidRestTestCase String queueName = getTestQueueName()+ "-lvq"; createQueue(queueName, "lvq", null); - Map<String, Object> hostDetails = getJsonAsSingletonList("/rest/virtualhost/test"); + Map<String, Object> hostDetails = getRestTestHelper().getJsonAsSingletonList("/rest/virtualhost/test"); @SuppressWarnings("unchecked") List<Map<String, Object>> queues = (List<Map<String, Object>>) hostDetails.get(VirtualHostRestTest.VIRTUALHOST_QUEUES_ATTRIBUTE); - Map<String, Object> lvqQueue = find(Queue.NAME, queueName , queues); + Map<String, Object> lvqQueue = getRestTestHelper().find(Queue.NAME, queueName , queues); Asserts.assertQueue(queueName , "lvq", lvqQueue); assertEquals("Unexpected value of queue attribute " + Queue.DURABLE, Boolean.TRUE, lvqQueue.get(Queue.DURABLE)); @@ -192,11 +192,11 @@ public class VirtualHostRestTest extends QpidRestTestCase int responseCode = tryCreateQueue(queueName, "sorted", null); assertEquals("Unexpected response code", 409, responseCode); - Map<String, Object> hostDetails = getJsonAsSingletonList("/rest/virtualhost/test"); + Map<String, Object> hostDetails = getRestTestHelper().getJsonAsSingletonList("/rest/virtualhost/test"); @SuppressWarnings("unchecked") List<Map<String, Object>> queues = (List<Map<String, Object>>) hostDetails.get(VirtualHostRestTest.VIRTUALHOST_QUEUES_ATTRIBUTE); - Map<String, Object> testQueue = find(Queue.NAME, queueName , queues); + Map<String, Object> testQueue = getRestTestHelper().find(Queue.NAME, queueName , queues); assertNull("Sorted queue without a key was created ", testQueue); } @@ -206,11 +206,11 @@ public class VirtualHostRestTest extends QpidRestTestCase String queueName = getTestQueueName()+ "-priority"; createQueue(queueName, "priority", null); - Map<String, Object> hostDetails = getJsonAsSingletonList("/rest/virtualhost/test"); + Map<String, Object> hostDetails = getRestTestHelper().getJsonAsSingletonList("/rest/virtualhost/test"); @SuppressWarnings("unchecked") List<Map<String, Object>> queues = (List<Map<String, Object>>) hostDetails.get(VirtualHostRestTest.VIRTUALHOST_QUEUES_ATTRIBUTE); - Map<String, Object> priorityQueue = find(Queue.NAME, queueName , queues); + Map<String, Object> priorityQueue = getRestTestHelper().find(Queue.NAME, queueName , queues); Asserts.assertQueue(queueName , "priority", priorityQueue); assertEquals("Unexpected value of queue attribute " + Queue.DURABLE, Boolean.TRUE, priorityQueue.get(Queue.DURABLE)); @@ -222,11 +222,11 @@ public class VirtualHostRestTest extends QpidRestTestCase String queueName = getTestQueueName(); createQueue(queueName, null, null); - Map<String, Object> hostDetails = getJsonAsSingletonList("/rest/virtualhost/test"); + Map<String, Object> hostDetails = getRestTestHelper().getJsonAsSingletonList("/rest/virtualhost/test"); @SuppressWarnings("unchecked") List<Map<String, Object>> queues = (List<Map<String, Object>>) hostDetails.get(VirtualHostRestTest.VIRTUALHOST_QUEUES_ATTRIBUTE); - Map<String, Object> queue = find(Queue.NAME, queueName , queues); + Map<String, Object> queue = getRestTestHelper().find(Queue.NAME, queueName , queues); Asserts.assertQueue(queueName , "standard", queue); } @@ -237,11 +237,11 @@ public class VirtualHostRestTest extends QpidRestTestCase int responseCode = tryCreateQueue(queueName, "unsupported", null); assertEquals("Unexpected response code", 409, responseCode); - Map<String, Object> hostDetails = getJsonAsSingletonList("/rest/virtualhost/test"); + Map<String, Object> hostDetails = getRestTestHelper().getJsonAsSingletonList("/rest/virtualhost/test"); @SuppressWarnings("unchecked") List<Map<String, Object>> queues = (List<Map<String, Object>>) hostDetails.get(VirtualHostRestTest.VIRTUALHOST_QUEUES_ATTRIBUTE); - Map<String, Object> queue = find(Queue.NAME, queueName , queues); + Map<String, Object> queue = getRestTestHelper().find(Queue.NAME, queueName , queues); assertNull("Queue of unsupported type was created", queue); } @@ -251,10 +251,10 @@ public class VirtualHostRestTest extends QpidRestTestCase String queueName = getTestQueueName(); createQueue(queueName, null, null); - HttpURLConnection connection = openManagementConection("/rest/queue/test/" + queueName, "DELETE"); + HttpURLConnection connection = getRestTestHelper().openManagementConnection("/rest/queue/test/" + queueName, "DELETE"); connection.connect(); assertEquals("Unexpected response code", 200, connection.getResponseCode()); - List<Map<String, Object>> queues = getJsonAsList("/rest/queue/test/" + queueName); + List<Map<String, Object>> queues = getRestTestHelper().getJsonAsList("/rest/queue/test/" + queueName); assertEquals("Queue should be deleted", 0, queues.size()); } @@ -262,12 +262,12 @@ public class VirtualHostRestTest extends QpidRestTestCase { String queueName = getTestQueueName(); createQueue(queueName, null, null); - Map<String, Object> queueDetails = getJsonAsSingletonList("/rest/queue/test/" + queueName); + Map<String, Object> queueDetails = getRestTestHelper().getJsonAsSingletonList("/rest/queue/test/" + queueName); - HttpURLConnection connection = openManagementConection("/rest/queue/test?id=" + queueDetails.get(Queue.ID), "DELETE"); + HttpURLConnection connection = getRestTestHelper().openManagementConnection("/rest/queue/test?id=" + queueDetails.get(Queue.ID), "DELETE"); connection.connect(); assertEquals("Unexpected response code", 200, connection.getResponseCode()); - List<Map<String, Object>> queues = getJsonAsList("/rest/queue/test/" + queueName); + List<Map<String, Object>> queues = getRestTestHelper().getJsonAsList("/rest/queue/test/" + queueName); assertEquals("Queue should be deleted", 0, queues.size()); } @@ -276,10 +276,10 @@ public class VirtualHostRestTest extends QpidRestTestCase String exchangeName = getTestName(); createExchange(exchangeName, "direct"); - HttpURLConnection connection = openManagementConection("/rest/exchange/test/" + exchangeName, "DELETE"); + HttpURLConnection connection = getRestTestHelper().openManagementConnection("/rest/exchange/test/" + exchangeName, "DELETE"); connection.connect(); assertEquals("Unexpected response code", 200, connection.getResponseCode()); - List<Map<String, Object>> queues = getJsonAsList("/rest/exchange/test/" + exchangeName); + List<Map<String, Object>> queues = getRestTestHelper().getJsonAsList("/rest/exchange/test/" + exchangeName); assertEquals("Exchange should be deleted", 0, queues.size()); } @@ -287,12 +287,12 @@ public class VirtualHostRestTest extends QpidRestTestCase { String exchangeName = getTestName(); createExchange(exchangeName, "direct"); - Map<String, Object> echangeDetails = getJsonAsSingletonList("/rest/exchange/test/" + exchangeName); + Map<String, Object> echangeDetails = getRestTestHelper().getJsonAsSingletonList("/rest/exchange/test/" + exchangeName); - HttpURLConnection connection = openManagementConection("/rest/exchange/test?id=" + echangeDetails.get(Exchange.ID), "DELETE"); + HttpURLConnection connection = getRestTestHelper().openManagementConnection("/rest/exchange/test?id=" + echangeDetails.get(Exchange.ID), "DELETE"); connection.connect(); assertEquals("Unexpected response code", 200, connection.getResponseCode()); - List<Map<String, Object>> queues = getJsonAsList("/rest/exchange/test/" + exchangeName); + List<Map<String, Object>> queues = getRestTestHelper().getJsonAsList("/rest/exchange/test/" + exchangeName); assertEquals("Exchange should be deleted", 0, queues.size()); } @@ -326,14 +326,14 @@ public class VirtualHostRestTest extends QpidRestTestCase lvqQueueAttributes.put(Queue.LVQ_KEY, "LVQ"); createQueue(queueName + "-lvq", "lvq", lvqQueueAttributes); - Map<String, Object> hostDetails = getJsonAsSingletonList("/rest/virtualhost/test"); + Map<String, Object> hostDetails = getRestTestHelper().getJsonAsSingletonList("/rest/virtualhost/test"); @SuppressWarnings("unchecked") List<Map<String, Object>> queues = (List<Map<String, Object>>) hostDetails.get(VirtualHostRestTest.VIRTUALHOST_QUEUES_ATTRIBUTE); - Map<String, Object> standardQueue = find(Queue.NAME, queueName + "-standard" , queues); - Map<String, Object> sortedQueue = find(Queue.NAME, queueName + "-sorted" , queues); - Map<String, Object> priorityQueue = find(Queue.NAME, queueName + "-priority" , queues); - Map<String, Object> lvqQueue = find(Queue.NAME, queueName + "-lvq" , queues); + Map<String, Object> standardQueue = getRestTestHelper().find(Queue.NAME, queueName + "-standard" , queues); + Map<String, Object> sortedQueue = getRestTestHelper().find(Queue.NAME, queueName + "-sorted" , queues); + Map<String, Object> priorityQueue = getRestTestHelper().find(Queue.NAME, queueName + "-priority" , queues); + Map<String, Object> lvqQueue = getRestTestHelper().find(Queue.NAME, queueName + "-lvq" , queues); attributes.put(Queue.DURABLE, Boolean.TRUE); Asserts.assertQueue(queueName + "-standard", "standard", standardQueue, attributes); @@ -355,25 +355,25 @@ public class VirtualHostRestTest extends QpidRestTestCase attributes.put(AMQQueueFactory.X_QPID_DLQ_ENABLED, true); //verify the starting state - Map<String, Object> hostDetails = getJsonAsSingletonList("/rest/virtualhost/test"); + Map<String, Object> hostDetails = getRestTestHelper().getJsonAsSingletonList("/rest/virtualhost/test"); List<Map<String, Object>> queues = (List<Map<String, Object>>) hostDetails.get(VirtualHostRestTest.VIRTUALHOST_QUEUES_ATTRIBUTE); List<Map<String, Object>> exchanges = (List<Map<String, Object>>) hostDetails.get(VirtualHostRestTest.VIRTUALHOST_EXCHANGES_ATTRIBUTE); - assertNull("queue should not have already been present", find(Queue.NAME, queueName , queues)); - assertNull("queue should not have already been present", find(Queue.NAME, queueName + "_DLQ" , queues)); - assertNull("exchange should not have already been present", find(Exchange.NAME, queueName + "_DLE" , exchanges)); + assertNull("queue should not have already been present", getRestTestHelper().find(Queue.NAME, queueName , queues)); + assertNull("queue should not have already been present", getRestTestHelper().find(Queue.NAME, queueName + "_DLQ" , queues)); + assertNull("exchange should not have already been present", getRestTestHelper().find(Exchange.NAME, queueName + "_DLE" , exchanges)); //create the queue createQueue(queueName, "standard", attributes); //verify the new queue, as well as the DLQueue and DLExchange have been created - hostDetails = getJsonAsSingletonList("/rest/virtualhost/test"); + hostDetails = getRestTestHelper().getJsonAsSingletonList("/rest/virtualhost/test"); queues = (List<Map<String, Object>>) hostDetails.get(VirtualHostRestTest.VIRTUALHOST_QUEUES_ATTRIBUTE); exchanges = (List<Map<String, Object>>) hostDetails.get(VirtualHostRestTest.VIRTUALHOST_EXCHANGES_ATTRIBUTE); - Map<String, Object> queue = find(Queue.NAME, queueName , queues); - Map<String, Object> dlqQueue = find(Queue.NAME, queueName + "_DLQ" , queues); - Map<String, Object> dlExchange = find(Exchange.NAME, queueName + "_DLE" , exchanges); + Map<String, Object> queue = getRestTestHelper().find(Queue.NAME, queueName , queues); + Map<String, Object> dlqQueue = getRestTestHelper().find(Queue.NAME, queueName + "_DLQ" , queues); + Map<String, Object> dlExchange = getRestTestHelper().find(Exchange.NAME, queueName + "_DLE" , exchanges); assertNotNull("queue should not have been present", queue); assertNotNull("queue should not have been present", dlqQueue); assertNotNull("exchange should not have been present", dlExchange); @@ -388,14 +388,14 @@ public class VirtualHostRestTest extends QpidRestTestCase private void createExchange(String exchangeName, String exchangeType) throws IOException { - HttpURLConnection connection = openManagementConection("/rest/exchange/test/" + exchangeName, "PUT"); + HttpURLConnection connection = getRestTestHelper().openManagementConnection("/rest/exchange/test/" + exchangeName, "PUT"); Map<String, Object> queueData = new HashMap<String, Object>(); queueData.put(Exchange.NAME, exchangeName); queueData.put(Exchange.DURABLE, Boolean.TRUE); queueData.put(Exchange.TYPE, exchangeType); - writeJsonRequest(connection, queueData); + getRestTestHelper().writeJsonRequest(connection, queueData); assertEquals("Unexpected response code", 201, connection.getResponseCode()); connection.disconnect(); @@ -411,7 +411,7 @@ public class VirtualHostRestTest extends QpidRestTestCase private int tryCreateQueue(String queueName, String queueType, Map<String, Object> attributes) throws IOException, JsonGenerationException, JsonMappingException { - HttpURLConnection connection = openManagementConection("/rest/queue/test/" + queueName, "PUT"); + HttpURLConnection connection = getRestTestHelper().openManagementConnection("/rest/queue/test/" + queueName, "PUT"); Map<String, Object> queueData = new HashMap<String, Object>(); queueData.put(Queue.NAME, queueName); @@ -425,7 +425,7 @@ public class VirtualHostRestTest extends QpidRestTestCase queueData.putAll(attributes); } - writeJsonRequest(connection, queueData); + getRestTestHelper().writeJsonRequest(connection, queueData); int responseCode = connection.getResponseCode(); connection.disconnect(); return responseCode; diff --git a/java/broker-plugins/management-http/src/test/java/org/apache/qpid/systest/rest/acl/GroupRestACLTest.java b/java/broker-plugins/management-http/src/test/java/org/apache/qpid/systest/rest/acl/GroupRestACLTest.java new file mode 100644 index 0000000000..f9f9fbfef0 --- /dev/null +++ b/java/broker-plugins/management-http/src/test/java/org/apache/qpid/systest/rest/acl/GroupRestACLTest.java @@ -0,0 +1,187 @@ +/* + * + * 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.systest.rest.acl; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.Map; +import java.util.Properties; + +import javax.servlet.http.HttpServletResponse; + +import org.apache.qpid.server.management.plugin.servlet.rest.QpidRestTestCase; +import org.apache.qpid.server.security.acl.AbstractACLTestCase; + +public class GroupRestACLTest extends QpidRestTestCase +{ + private static final String FILE_GROUP_MANAGER = "FileGroupManager"; + + private static final String ALLOWED_GROUP = "allowedGroup"; + private static final String DENIED_GROUP = "deniedGroup"; + private static final String OTHER_GROUP = "otherGroup"; + + private static final String ALLOWED_USER = "webadmin"; + private static final String DENIED_USER = "admin"; + private static final String OTHER_USER = "admin"; + + private File _groupFile; + + @Override + public void setUp() throws Exception + { + _groupFile = createTemporaryGroupFile(); + + setConfigurationProperty("security.file-group-manager.attributes.attribute.name", "groupFile"); + setConfigurationProperty("security.file-group-manager.attributes.attribute.value", _groupFile.getAbsolutePath()); + + //DONT call super.setUp(), the tests will start the broker after configuring it + } + + @Override + public void tearDown() throws Exception + { + super.tearDown(); + + if (_groupFile != null) + { + if (_groupFile.exists()) + { + _groupFile.delete(); + } + } + } + + private File createTemporaryGroupFile() throws Exception + { + File groupFile = File.createTempFile("group", "grp"); + groupFile.deleteOnExit(); + + Properties props = new Properties(); + props.put(ALLOWED_GROUP + ".users", ALLOWED_USER); + props.put(DENIED_GROUP + ".users", DENIED_USER); + props.put(OTHER_GROUP + ".users", OTHER_USER); + + props.store(new FileOutputStream(groupFile), "test group file"); + + return groupFile; + } + + public void testCreateGroup() throws Exception + { + AbstractACLTestCase.writeACLFileUtil(this, null, + "ACL ALLOW-LOG " + ALLOWED_GROUP + " CREATE GROUP", + "ACL DENY-LOG " + DENIED_GROUP + " CREATE GROUP"); + + //Start the broker with the custom config + super.setUp(); + getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER); + + Map<String, Object> data = getRestTestHelper().getJsonAsSingletonList("/rest/groupprovider/" + FILE_GROUP_MANAGER); + getRestTestHelper().assertNumberOfGroups(data, 3); + + getRestTestHelper().createGroup("newGroup", FILE_GROUP_MANAGER); + + data = getRestTestHelper().getJsonAsSingletonList("/rest/groupprovider/" + FILE_GROUP_MANAGER); + getRestTestHelper().assertNumberOfGroups(data, 4); + + getRestTestHelper().setUsernameAndPassword(DENIED_USER, DENIED_USER); + + //TODO: the expected response code needs changed when we overhaul the brokers error handling + getRestTestHelper().createGroup("anotherNewGroup", FILE_GROUP_MANAGER, HttpServletResponse.SC_CONFLICT); + + data = getRestTestHelper().getJsonAsSingletonList("/rest/groupprovider/" + FILE_GROUP_MANAGER); + getRestTestHelper().assertNumberOfGroups(data, 4); + } + + public void testDeleteGroup() throws Exception + { + AbstractACLTestCase.writeACLFileUtil(this, null, + "ACL ALLOW-LOG " + ALLOWED_GROUP + " DELETE GROUP", + "ACL DENY-LOG " + DENIED_GROUP + " DELETE GROUP"); + + //Start the broker with the custom config + super.setUp(); + getRestTestHelper().setUsernameAndPassword(DENIED_USER, DENIED_USER); + + Map<String, Object> data = getRestTestHelper().getJsonAsSingletonList("/rest/groupprovider/" + FILE_GROUP_MANAGER); + getRestTestHelper().assertNumberOfGroups(data, 3); + + //TODO: the expected response code needs changed when we overhaul the brokers error handling + getRestTestHelper().removeGroup(OTHER_GROUP, FILE_GROUP_MANAGER, HttpServletResponse.SC_CONFLICT); + + data = getRestTestHelper().getJsonAsSingletonList("/rest/groupprovider/" + FILE_GROUP_MANAGER); + getRestTestHelper().assertNumberOfGroups(data, 3); + + getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER); + + getRestTestHelper().removeGroup(OTHER_GROUP, FILE_GROUP_MANAGER); + + data = getRestTestHelper().getJsonAsSingletonList("/rest/groupprovider/" + FILE_GROUP_MANAGER); + getRestTestHelper().assertNumberOfGroups(data, 2); + } + + public void testUpdateGroupAddMember() throws Exception + { + AbstractACLTestCase.writeACLFileUtil(this, null, + "ACL ALLOW-LOG " + ALLOWED_GROUP + " UPDATE GROUP", + "ACL DENY-LOG " + DENIED_GROUP + " UPDATE GROUP"); + + //Start the broker with the custom config + super.setUp(); + getRestTestHelper().setUsernameAndPassword(DENIED_USER, DENIED_USER); + + assertNumberOfGroupMembers(OTHER_GROUP, 1); + + getRestTestHelper().createNewGroupMember(FILE_GROUP_MANAGER, OTHER_GROUP, "newGroupMember", HttpServletResponse.SC_CONFLICT); + assertNumberOfGroupMembers(OTHER_GROUP, 1); + + getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER); + getRestTestHelper().createNewGroupMember(FILE_GROUP_MANAGER, OTHER_GROUP, "newGroupMember"); + assertNumberOfGroupMembers(OTHER_GROUP, 2); + } + + public void testUpdateGroupDeleteMember() throws Exception + { + AbstractACLTestCase.writeACLFileUtil(this, null, + "ACL ALLOW-LOG " + ALLOWED_GROUP + " UPDATE GROUP", + "ACL DENY-LOG " + DENIED_GROUP + " UPDATE GROUP"); + + //Start the broker with the custom config + super.setUp(); + getRestTestHelper().setUsernameAndPassword(DENIED_USER, DENIED_USER); + + assertNumberOfGroupMembers(OTHER_GROUP, 1); + + getRestTestHelper().removeMemberFromGroup(FILE_GROUP_MANAGER, OTHER_GROUP, OTHER_USER, HttpServletResponse.SC_CONFLICT); + assertNumberOfGroupMembers(OTHER_GROUP, 1); + + getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER); + getRestTestHelper().removeMemberFromGroup(FILE_GROUP_MANAGER, OTHER_GROUP, OTHER_USER); + assertNumberOfGroupMembers(OTHER_GROUP, 0); + } + + private void assertNumberOfGroupMembers(String groupName, int expectedNumberOfMembers) throws IOException + { + Map<String, Object> group = getRestTestHelper().getJsonAsSingletonList("/rest/group/FileGroupManager/" + groupName); + getRestTestHelper().assertNumberOfGroupMembers(group, expectedNumberOfMembers); + } +} diff --git a/java/broker-plugins/management-http/src/test/java/org/apache/qpid/systest/rest/acl/UserRestACLTest.java b/java/broker-plugins/management-http/src/test/java/org/apache/qpid/systest/rest/acl/UserRestACLTest.java new file mode 100644 index 0000000000..514d1bd781 --- /dev/null +++ b/java/broker-plugins/management-http/src/test/java/org/apache/qpid/systest/rest/acl/UserRestACLTest.java @@ -0,0 +1,188 @@ +/* + * 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.systest.rest.acl; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.net.HttpURLConnection; +import java.util.List; +import java.util.Map; +import java.util.Properties; + +import javax.servlet.http.HttpServletResponse; + +import org.apache.qpid.server.management.plugin.servlet.rest.QpidRestTestCase; +import org.apache.qpid.server.security.acl.AbstractACLTestCase; +import org.codehaus.jackson.JsonParseException; +import org.codehaus.jackson.map.JsonMappingException; + +public class UserRestACLTest extends QpidRestTestCase +{ + private static final String ALLOWED_GROUP = "allowedGroup"; + private static final String DENIED_GROUP = "deniedGroup"; + private static final String OTHER_GROUP = "otherGroup"; + + private static final String ALLOWED_USER = "webadmin"; + private static final String DENIED_USER = "admin"; + private static final String OTHER_USER = "other"; + + private File _groupFile; + + @Override + public void setUp() throws Exception + { + _groupFile = createTemporaryGroupFile(); + + setConfigurationProperty("security.file-group-manager.attributes.attribute.name", "groupFile"); + setConfigurationProperty("security.file-group-manager.attributes.attribute.value", _groupFile.getAbsolutePath()); + + getRestTestHelper().configureTemporaryPasswordFile(this, ALLOWED_USER, DENIED_USER, OTHER_USER); + + //DONT call super.setUp(), the tests will start the broker after configuring it + } + + @Override + public void tearDown() throws Exception + { + super.tearDown(); + + if (_groupFile != null) + { + if (_groupFile.exists()) + { + _groupFile.delete(); + } + } + } + + private File createTemporaryGroupFile() throws Exception + { + File groupFile = File.createTempFile("group", "grp"); + groupFile.deleteOnExit(); + + Properties props = new Properties(); + props.put(ALLOWED_GROUP + ".users", ALLOWED_USER); + props.put(DENIED_GROUP + ".users", DENIED_USER); + props.put(OTHER_GROUP + ".users", OTHER_USER); + + props.store(new FileOutputStream(groupFile), "test group file"); + + return groupFile; + } + + public void testAddUser() throws Exception + { + AbstractACLTestCase.writeACLFileUtil(this, null, + "ACL ALLOW-LOG " + ALLOWED_GROUP + " CREATE USER", + "ACL DENY-LOG " + DENIED_GROUP + " CREATE USER"); + + //Start the broker with the custom config + super.setUp(); + + String newUser = "newUser"; + String password = "password"; + + assertUserDoesNotExist(newUser); + + getRestTestHelper().setUsernameAndPassword(DENIED_USER, DENIED_USER); + + getRestTestHelper().createOrUpdateUser(newUser, password, HttpServletResponse.SC_CONFLICT); + assertUserDoesNotExist(newUser); + + getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER); + getRestTestHelper().createOrUpdateUser(newUser, password); + assertUserExists(newUser); + } + + public void testDeleteUser() throws Exception + { + AbstractACLTestCase.writeACLFileUtil(this, null, + "ACL ALLOW-LOG " + ALLOWED_GROUP + " DELETE USER", + "ACL DENY-LOG " + DENIED_GROUP + " DELETE USER"); + + //Start the broker with the custom config + super.setUp(); + + assertUserExists(OTHER_USER); + + getRestTestHelper().setUsernameAndPassword(DENIED_USER, DENIED_USER); + getRestTestHelper().removeUser(OTHER_USER, HttpServletResponse.SC_CONFLICT); + assertUserExists(OTHER_USER); + + getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER); + getRestTestHelper().removeUser(OTHER_USER); + assertUserDoesNotExist(OTHER_USER); + } + + public void testUpdateUser() throws Exception + { + AbstractACLTestCase.writeACLFileUtil(this, null, + "ACL ALLOW-LOG " + ALLOWED_GROUP + " UPDATE USER", + "ACL DENY-LOG " + DENIED_GROUP + " UPDATE USER"); + + //Start the broker with the custom config + super.setUp(); + + String newPassword = "newPassword"; + + checkPassword(OTHER_USER, OTHER_USER, true); + + getRestTestHelper().setUsernameAndPassword(DENIED_USER, DENIED_USER); + getRestTestHelper().createOrUpdateUser(OTHER_USER, newPassword, HttpServletResponse.SC_CONFLICT); + + checkPassword(OTHER_USER, newPassword, false); + + getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER); + getRestTestHelper().createOrUpdateUser(OTHER_USER, newPassword, HttpServletResponse.SC_OK); // expect SC_OK rather than the default SC_CREATED + + checkPassword(OTHER_USER, newPassword, true); + checkPassword(OTHER_USER, OTHER_USER, false); + } + + private void checkPassword(String username, String password, boolean passwordExpectedToBeCorrect) throws IOException + { + getRestTestHelper().setUsernameAndPassword(username, password); + HttpURLConnection connection = getRestTestHelper().openManagementConnection("/rest/user/PrincipalDatabaseAuthenticationManager/", "GET"); + + boolean passwordIsCorrect = connection.getResponseCode() == HttpServletResponse.SC_OK; + + connection.disconnect(); + + assertEquals(passwordExpectedToBeCorrect, passwordIsCorrect); + } + + private void assertUserDoesNotExist(String newUser) throws JsonParseException, JsonMappingException, IOException + { + String path = "/rest/user/PrincipalDatabaseAuthenticationManager/" + newUser; + List<Map<String, Object>> userDetailsList = getRestTestHelper().getJsonAsList(path); + assertTrue(userDetailsList.isEmpty()); + } + + private void assertUserExists(String username) throws IOException + { + String path = "/rest/user/PrincipalDatabaseAuthenticationManager/" + username; + Map<String, Object> userDetails = getRestTestHelper().getJsonAsSingletonList(path); + + assertEquals( + "User returned by " + path + " should have name=" + username + ". The returned JSON was: " + userDetails, + username, + userDetails.get("name")); + } +} diff --git a/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXManagedObjectRegistry.java b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXManagedObjectRegistry.java index 0648235077..e68c0d650b 100644 --- a/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXManagedObjectRegistry.java +++ b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXManagedObjectRegistry.java @@ -29,9 +29,8 @@ import org.apache.qpid.server.logging.messages.ManagementConsoleMessages; import org.apache.qpid.server.registry.ApplicationRegistry; import org.apache.qpid.server.registry.IApplicationRegistry; +import org.apache.qpid.server.security.auth.AuthenticatedPrincipal; import org.apache.qpid.server.security.auth.rmi.RMIPasswordAuthenticator; -import org.apache.qpid.server.security.auth.sasl.UsernamePrincipal; - import javax.management.JMException; import javax.management.MBeanServer; import javax.management.MBeanServerFactory; @@ -73,7 +72,7 @@ import java.util.Map; import java.util.concurrent.ConcurrentHashMap; /** - * This class starts up an MBeanserver. If out of the box agent has been enabled then there are no + * This class starts up an MBeanserver. If out of the box agent has been enabled then there are no * security features implemented like user authentication and authorisation. */ public class JMXManagedObjectRegistry implements ManagedObjectRegistry @@ -244,8 +243,8 @@ public class JMXManagedObjectRegistry implements ManagedObjectRegistry protected RMIConnection makeClient(String connectionId, Subject subject) throws IOException { final RMIConnection makeClient = super.makeClient(connectionId, subject); - final UsernamePrincipal usernamePrincipalFromSubject = UsernamePrincipal.getUsernamePrincipalFromSubject(subject); - connectionIdUsernameMap.put(connectionId, usernamePrincipalFromSubject.getName()); + final AuthenticatedPrincipal authenticatedPrincipalFromSubject = AuthenticatedPrincipal.getAuthenticatedPrincipalFromSubject(subject); + connectionIdUsernameMap.put(connectionId, authenticatedPrincipalFromSubject.getName()); return makeClient; } }; @@ -451,7 +450,7 @@ public class JMXManagedObjectRegistry implements ManagedObjectRegistry _log.error("Exception while closing the JMX ConnectorServer: ", e); } } - + if (_rmiRegistry != null) { // Stopping the RMI registry @@ -469,7 +468,7 @@ public class JMXManagedObjectRegistry implements ManagedObjectRegistry _log.error("Exception while closing the RMI Registry: ", e); } } - + //ObjectName query to gather all Qpid related MBeans ObjectName mbeanNameQuery = null; try diff --git a/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/MBeanInvocationHandlerImpl.java b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/MBeanInvocationHandlerImpl.java index a2a0d2d093..694b0b2913 100644 --- a/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/MBeanInvocationHandlerImpl.java +++ b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/MBeanInvocationHandlerImpl.java @@ -30,6 +30,7 @@ import org.apache.qpid.server.registry.ApplicationRegistry; import org.apache.qpid.server.registry.IApplicationRegistry; import org.apache.qpid.server.security.SecurityManager; import org.apache.qpid.server.security.access.Operation; +import org.apache.qpid.server.security.auth.AuthenticatedPrincipal; import javax.management.Attribute; import javax.management.JMException; @@ -41,7 +42,6 @@ import javax.management.NotificationListener; import javax.management.ObjectName; import javax.management.RuntimeErrorException; import javax.management.remote.JMXConnectionNotification; -import javax.management.remote.JMXPrincipal; import javax.management.remote.MBeanServerForwarder; import javax.security.auth.Subject; import java.lang.reflect.InvocationHandler; @@ -52,7 +52,6 @@ import java.security.AccessControlContext; import java.security.AccessController; import java.util.Arrays; import java.util.Map; -import java.util.Set; /** * This class can be used by the JMXConnectorServer as an InvocationHandler for the mbean operations. It delegates @@ -101,7 +100,7 @@ public class MBeanInvocationHandlerImpl implements InvocationHandler, Notificati { ObjectName mbean = (ObjectName) args[0]; - if(!DefaultManagedObject.DOMAIN.equalsIgnoreCase(mbean.getDomain())) + if(!ManagedObject.DOMAIN.equalsIgnoreCase(mbean.getDomain())) { return true; } @@ -151,11 +150,13 @@ public class MBeanInvocationHandlerImpl implements InvocationHandler, Notificati return method.invoke(_mbs, args); } - // Retrieve JMXPrincipal from Subject - Set<JMXPrincipal> principals = subject.getPrincipals(JMXPrincipal.class); - if (principals == null || principals.isEmpty()) + try + { + AuthenticatedPrincipal.getAuthenticatedPrincipalFromSubject(subject); + } + catch(Exception e) { - throw new SecurityException("Access denied: no JMX principal"); + throw new SecurityException("Access denied: no authenticated principal", e); } // Save the subject @@ -381,6 +382,7 @@ public class MBeanInvocationHandlerImpl implements InvocationHandler, Notificati String user = null; if (handback instanceof Map) { + @SuppressWarnings("unchecked") final Map<String, String> connectionIdUsernameMap = (Map<String, String>) handback; user = connectionIdUsernameMap.get(connectionId); } |
