[jboss-cvs] JBossAS SVN: r114607 - in branches/JBPAPP_5: testsuite/src/main/org/jboss/test/jmx/invoker and 1 other directories.
jboss-cvs-commits at lists.jboss.org
jboss-cvs-commits at lists.jboss.org
Wed Dec 18 03:20:35 EST 2013
Author: baranowb
Date: 2013-12-18 03:20:34 -0500 (Wed, 18 Dec 2013)
New Revision: 114607
Added:
branches/JBPAPP_5/testsuite/src/main/org/jboss/test/jmx/invoker/authorization/
branches/JBPAPP_5/testsuite/src/main/org/jboss/test/jmx/invoker/authorization/RolesAuthorizationTestCase.java
branches/JBPAPP_5/testsuite/src/main/org/jboss/test/jmx/invoker/authorization/jmx-security-roles.xml
Modified:
branches/JBPAPP_5/server/src/main/org/jboss/jmx/connector/invoker/authorization/roles/AuthorizationTarget.java
branches/JBPAPP_5/server/src/main/org/jboss/jmx/connector/invoker/authorization/roles/Operation.java
branches/JBPAPP_5/server/src/main/org/jboss/jmx/connector/invoker/authorization/roles/Parser.java
branches/JBPAPP_5/server/src/main/org/jboss/jmx/connector/invoker/authorization/roles/RolesAuthorization.java
Log:
JBPAPP-10716 fix
Modified: branches/JBPAPP_5/server/src/main/org/jboss/jmx/connector/invoker/authorization/roles/AuthorizationTarget.java
===================================================================
--- branches/JBPAPP_5/server/src/main/org/jboss/jmx/connector/invoker/authorization/roles/AuthorizationTarget.java 2013-12-17 16:07:03 UTC (rev 114606)
+++ branches/JBPAPP_5/server/src/main/org/jboss/jmx/connector/invoker/authorization/roles/AuthorizationTarget.java 2013-12-18 08:20:34 UTC (rev 114607)
@@ -22,7 +22,9 @@
package org.jboss.jmx.connector.invoker.authorization.roles;
+import java.util.List;
import java.util.Map;
+import java.util.regex.Pattern;
import javax.management.ObjectName;
@@ -35,13 +37,13 @@
public class AuthorizationTarget {
private ObjectName objectName;
- private Map<String, Operation> operations;
+ private List<Operation> operations;
/**
* @param objectName
* @param operations2
*/
- public AuthorizationTarget(ObjectName objectName, Map<String, Operation> operations) {
+ public AuthorizationTarget(ObjectName objectName, List<Operation> operations) {
this.objectName = objectName;
this.operations = operations;
}
@@ -51,7 +53,14 @@
* @return
*/
public Operation matchOperation(String opname) {
- final Operation target = operations.get(opname);
+ Operation target = null;
+ for(int index = 0; index < operations.size(); index++){
+ Operation o = this.operations.get(index);
+ if(Pattern.matches(o.getName(), opname)){
+ target = o;
+ break;
+ }
+ }
if (target == null) {
throw new SecurityException("No rules defined at: '" + objectName + "' for operation: " + opname);
Modified: branches/JBPAPP_5/server/src/main/org/jboss/jmx/connector/invoker/authorization/roles/Operation.java
===================================================================
--- branches/JBPAPP_5/server/src/main/org/jboss/jmx/connector/invoker/authorization/roles/Operation.java 2013-12-17 16:07:03 UTC (rev 114606)
+++ branches/JBPAPP_5/server/src/main/org/jboss/jmx/connector/invoker/authorization/roles/Operation.java 2013-12-18 08:20:34 UTC (rev 114607)
@@ -40,7 +40,7 @@
/**
* @param name
- * @param roles
+ * @param roles
* @param objectName
*/
public Operation(String name, List<Principal> roles, ObjectName objectName) {
@@ -59,6 +59,9 @@
while (it.hasNext() && hasRole == false) {
Principal p = it.next();
hasRole = roles.isMember(p);
+ if (hasRole) {
+ break;
+ }
}
if (hasRole == false) {
throw new SecurityException("Authorization failure,target='" + objectName + "', operation='" + name
Modified: branches/JBPAPP_5/server/src/main/org/jboss/jmx/connector/invoker/authorization/roles/Parser.java
===================================================================
--- branches/JBPAPP_5/server/src/main/org/jboss/jmx/connector/invoker/authorization/roles/Parser.java 2013-12-17 16:07:03 UTC (rev 114606)
+++ branches/JBPAPP_5/server/src/main/org/jboss/jmx/connector/invoker/authorization/roles/Parser.java 2013-12-18 08:20:34 UTC (rev 114607)
@@ -104,7 +104,7 @@
final Element nameElement = (Element) list.item(0);
final String name = nameElement.getTextContent();
final ObjectName objectName = new ObjectName(name);
- Map<String, Operation> operations = new HashMap<String, Operation>();
+ List<Operation> operations = new ArrayList<Operation>();
list = (NodeList) (XPATH.evaluate(OPERATIONS, authorizationTarget, XPathConstants.NODESET));
if (list.getLength() == 0) {
@@ -116,7 +116,7 @@
final int count = list.getLength();
for (int index = 0; index < count; index++) {
Operation op = parseOperation(list.item(index), objectName);
- operations.put(op.getName(), op);
+ operations.add(op);
}
return new AuthorizationTarget(objectName, operations);
Modified: branches/JBPAPP_5/server/src/main/org/jboss/jmx/connector/invoker/authorization/roles/RolesAuthorization.java
===================================================================
--- branches/JBPAPP_5/server/src/main/org/jboss/jmx/connector/invoker/authorization/roles/RolesAuthorization.java 2013-12-17 16:07:03 UTC (rev 114606)
+++ branches/JBPAPP_5/server/src/main/org/jboss/jmx/connector/invoker/authorization/roles/RolesAuthorization.java 2013-12-18 08:20:34 UTC (rev 114607)
@@ -22,10 +22,12 @@
package org.jboss.jmx.connector.invoker.authorization.roles;
+import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.security.Principal;
import java.security.acl.Group;
+import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
@@ -36,6 +38,8 @@
import javax.management.ObjectName;
import javax.security.auth.Subject;
+import org.jboss.security.SimpleGroup;
+
/**
* Roles based authorization. This is advanced version of {@link org.jboss.jmx.connector.invoker.RolesAuthorization}. It
* provides fine grained check against:
@@ -45,11 +49,35 @@
* <li>user role</li> - determines( just like {@link org.jboss.jmx.connector.invoker.RolesAuthorization}) if current subject has
* required role.
* </ul>
- * This allows to define per role access level to certain MBeans and their methods. This implementation does not support wild
- * cards. It requires strict rules definition. If no rule is defined for target/method - it will deny access. Default
- * implementation requires configuration file(<b>jmx-security-roles.xml</b>) to be present in
- * <b>$JBOSS_HOME/server/${node}/conf</b>.<br>
+ * This allows to define per role access level to certain MBeans and their methods. Default implementation requires
+ * configuration file(<b>jmx-security-roles.xml</b>) to be present in <b>$JBOSS_HOME/server/${node}/conf</b>.<br>
* Configuration file format looks as follows:<br>
+ * <br>
+ * <br>
+ * Note that 'wildcards' are supported. Valid MBean names:<br>
+ * <ul>
+ * <li>jboss:type=simple</li>
+ * <li>jboss:type=*</li>
+ * <li>jboss:*</li>
+ * </ul>
+ * <br>
+ * Operation names support regular expression, valid operation names:
+ * <ul>
+ * <li>invoke</li>
+ * <li>get*</li>
+ * <li>getData</li>
+ * </ul>
+ * <br>
+ * Be aware that this implementation considers rules as chains. This means that order of rule definition is important, in case
+ * of operation name and MBean name. <br>
+ * If authorization-target(3) MBean name match desired name, the authorization-target(4) is not processed, even though it may
+ * match MBean name:<br>
+ * desired name: jboss:data=simple,name=myname<br>
+ * authorization-target(3): jboss:data=simple,*<br>
+ * authorization-target(4): jboss:*<br>
+ * Operation name match works in similar way. <br>
+ * <br>
+ * Example configuration entry:
*
* <pre>
* <authorization-rules>
@@ -96,9 +124,9 @@
*/
public class RolesAuthorization {
- private static final String CONFIGURATION_FILE = "jmx-security-roles.xml";
+ protected static final String CONFIGURATION_FILE = "jmx-security-roles.xml";
- private final Map<ObjectName, AuthorizationTarget> oname2Authorization = new HashMap<ObjectName, AuthorizationTarget>();
+ private List<AuthorizationTarget> authorizationTargets;
/**
*
@@ -109,11 +137,11 @@
}
public void authorize(Principal caller, Subject subject, String objectname, String opname) {
- Set groups = subject.getPrincipals(Group.class);
+ final Set<Group> groups = subject.getPrincipals(Group.class);
Group roles = null;
- Iterator iter = groups.iterator();
+ final Iterator<Group> iter = groups.iterator();
while (iter.hasNext()) {
- Group grp = (Group) iter.next();
+ Group grp = iter.next();
if (grp.getName().equals("Roles")) {
roles = grp;
break;
@@ -123,10 +151,9 @@
throw new SecurityException("Subject has no Roles, there is no way to assert access privilege!");
}
- AuthorizationTarget target = matchTraget(objectname);
+ final AuthorizationTarget target = matchTraget(objectname);
+ final Operation operation = target.matchOperation(opname);
- Operation operation = target.matchOperation(opname);
-
operation.assertPrivilege(roles);
}
@@ -140,7 +167,14 @@
} catch (NullPointerException e) {
throw new SecurityException("Malformed taget name: '" + objectName + "'");
}
- AuthorizationTarget target = this.oname2Authorization.get(name);
+ AuthorizationTarget target = null;
+ for (int index = 0; index < this.authorizationTargets.size(); index++) {
+ AuthorizationTarget at = this.authorizationTargets.get(index);
+ if (at.getObjectName().apply(name)) {
+ target = at;
+ break;
+ }
+ }
if (target == null) {
throw new SecurityException("No rules defined for: '" + objectName + "'");
@@ -151,21 +185,25 @@
protected void configure() throws Exception {
InputStream is = null;
try {
- is = Thread.currentThread().getContextClassLoader().getResourceAsStream(CONFIGURATION_FILE);
- if (is == null) {
- throw new IOException("Failed to read configuration file '" + CONFIGURATION_FILE
- + "' from server 'conf' directory!");
- }
- List<AuthorizationTarget> targets = Parser.parse(is);
- for (AuthorizationTarget t : targets) {
- this.oname2Authorization.put(t.getObjectName(), t);
- }
+ is = this.getConfigurationStream();
+ this.authorizationTargets = Parser.parse(is);
} finally {
- if(is != null){
- try{
+ if (is != null) {
+ try {
is.close();
- }catch(Exception e){}
+ } catch (Exception e) {
+ }
}
}
}
+
+ protected InputStream getConfigurationStream() throws Exception {
+ InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(CONFIGURATION_FILE);
+ if (is == null) {
+ throw new IOException("Failed to read configuration file '" + CONFIGURATION_FILE
+ + "' from server 'conf' directory!");
+ }
+ return is;
+
+ }
}
\ No newline at end of file
Added: branches/JBPAPP_5/testsuite/src/main/org/jboss/test/jmx/invoker/authorization/RolesAuthorizationTestCase.java
===================================================================
--- branches/JBPAPP_5/testsuite/src/main/org/jboss/test/jmx/invoker/authorization/RolesAuthorizationTestCase.java (rev 0)
+++ branches/JBPAPP_5/testsuite/src/main/org/jboss/test/jmx/invoker/authorization/RolesAuthorizationTestCase.java 2013-12-18 08:20:34 UTC (rev 114607)
@@ -0,0 +1,200 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2013, Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.test.jmx.invoker.authorization;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.security.Principal;
+import java.security.acl.Group;
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.security.auth.Subject;
+
+import org.jboss.jmx.connector.invoker.authorization.roles.RolesAuthorization;
+import org.jboss.security.SimpleGroup;
+import org.jboss.security.SimplePrincipal;
+import org.jboss.test.JBossTestCase;
+
+/**
+ * @author baranowb
+ *
+ */
+public class RolesAuthorizationTestCase extends JBossTestCase {
+ private RolesAuthorization authorization;
+
+ /**
+ * @param name
+ */
+ public RolesAuthorizationTestCase(String name) {
+ super(name);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ this.authorization = new RolesAuthorization() {
+ @Override
+ protected InputStream getConfigurationStream() throws Exception {
+ return new FileInputStream(new File(".." + File.separator + "src" + File.separator + "main" + File.separator
+ + "org" + File.separator + "jboss" + File.separator + "test" + File.separator + "jmx" + File.separator
+ + "invoker" + File.separator + "authorization" + File.separator + super.CONFIGURATION_FILE));
+ }
+
+ };
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ this.authorization = null;
+ super.tearDown();
+ }
+
+ public void testAuthorization() throws Exception {
+ final String objectName = "jboss:service=JNDIView";
+ final String opName = "list";
+ final Principal caller = new SimplePrincipal("test");
+ // yeah, this is stupid
+ final Group group = new SimpleGroup("Roles");
+ group.addMember(new SimplePrincipal("Tester"));
+ final Set callers = new HashSet();
+ callers.add(caller);
+ callers.add(group);
+ final Subject subject = new Subject(false, callers, new HashSet(), new HashSet());
+ authorization.authorize(caller, subject, objectName, opName);
+ }
+
+ public void testWildarcMatch() throws Exception {
+ final String objectName = "jboss:service=NO_BOOM";
+ final String opName = "list";
+ final Principal caller = new SimplePrincipal("test");
+ // yeah, this is stupid
+ final Group group = new SimpleGroup("Roles");
+ group.addMember(new SimplePrincipal("Tester"));
+ final Set callers = new HashSet();
+ callers.add(caller);
+ callers.add(group);
+ final Subject subject = new Subject(false, callers, new HashSet(), new HashSet());
+ try {
+ authorization.authorize(caller, subject, objectName, opName);
+ } catch (SecurityException se) {
+ fail("Did not expect exception");
+ }
+ }
+ public void testWildarcMatch_2() throws Exception {
+ //this is ! to testNoRule_3
+ final String objectName = "jboss:type=NO_BOOM";
+ final String opName = "getSomeThingThatDoesNotExist";
+ final Principal caller = new SimplePrincipal("test");
+ // yeah, this is stupid
+ final Group group = new SimpleGroup("Roles");
+ group.addMember(new SimplePrincipal("Tester"));
+ final Set callers = new HashSet();
+ callers.add(caller);
+ callers.add(group);
+ final Subject subject = new Subject(false, callers, new HashSet(), new HashSet());
+ try {
+ authorization.authorize(caller, subject, objectName, opName);
+ } catch (SecurityException se) {
+ fail("Did not expect exception");
+ }
+ }
+ public void testNoRule() throws Exception {
+ final String objectName = "jboss:service=BOOM";
+ final String opName = "list";
+ final Principal caller = new SimplePrincipal("test");
+ // yeah, this is stupid
+ final Group group = new SimpleGroup("Roles");
+ group.addMember(new SimplePrincipal("JBossAdmin"));
+ final Set callers = new HashSet();
+ callers.add(caller);
+ callers.add(group);
+ final Subject subject = new Subject(false, callers, new HashSet(), new HashSet());
+ try {
+ authorization.authorize(caller, subject, objectName, opName);
+ fail("Expected SecurityException since there is no rule!");
+ } catch (SecurityException se) {
+ //
+ }
+ }
+
+ public void testNoRule_2() throws Exception {
+ final String objectName = "wicked_domain:service=BOOM";
+ final String opName = "list";
+ final Principal caller = new SimplePrincipal("test");
+ // yeah, this is stupid
+ final Group group = new SimpleGroup("Roles");
+ group.addMember(new SimplePrincipal("JBossAdmin"));
+ final Set callers = new HashSet();
+ callers.add(caller);
+ callers.add(group);
+ final Subject subject = new Subject(false, callers, new HashSet(), new HashSet());
+ try {
+ authorization.authorize(caller, subject, objectName, opName);
+ fail("Expected SecurityException since there is no rule!");
+ } catch (SecurityException se) {
+ //
+ }
+ }
+
+ public void testNoRule_3() throws Exception {
+ //test if first rule op def will match - it has only Tester role.
+ //second rule should never be triggered
+ final String objectName = "jboss:type=NO_BOOM";
+ final String opName = "getSomeThingThatDoesNotExist";
+ final Principal caller = new SimplePrincipal("test");
+ // yeah, this is stupid
+ final Group group = new SimpleGroup("Roles");
+ group.addMember(new SimplePrincipal("JBossAdmin"));
+ final Set callers = new HashSet();
+ callers.add(caller);
+ callers.add(group);
+ final Subject subject = new Subject(false, callers, new HashSet(), new HashSet());
+ try {
+ authorization.authorize(caller, subject, objectName, opName);
+ fail("Expected SecurityException since there is no rule!");
+ } catch (SecurityException se) {
+ //
+ }
+ }
+
+ public void testAuthorizationFailure() throws Exception {
+ final String objectName = "jboss:service=JNDIView";
+ final String opName = "list";
+ final Principal caller = new SimplePrincipal("test");
+ // yeah, this is stupid
+ final Group group = new SimpleGroup("Roles");
+ group.addMember(new SimplePrincipal("IWillBoom"));
+ final Set callers = new HashSet();
+ callers.add(caller);
+ callers.add(group);
+ final Subject subject = new Subject(false, callers, new HashSet(), new HashSet());
+ try {
+ authorization.authorize(caller, subject, objectName, opName);
+ fail("Expected SecurityException since there is no role!");
+ } catch (SecurityException se) {
+ //
+ }
+ }
+}
Added: branches/JBPAPP_5/testsuite/src/main/org/jboss/test/jmx/invoker/authorization/jmx-security-roles.xml
===================================================================
--- branches/JBPAPP_5/testsuite/src/main/org/jboss/test/jmx/invoker/authorization/jmx-security-roles.xml (rev 0)
+++ branches/JBPAPP_5/testsuite/src/main/org/jboss/test/jmx/invoker/authorization/jmx-security-roles.xml 2013-12-18 08:20:34 UTC (rev 114607)
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<authorization-rules>
+ <authorization-target>
+ <name>jboss:service=JNDIView</name>
+ <operations>
+ <operation>
+ <name>queryNames</name>
+ <roles>
+ <role>JBossAdmin</role>
+ <role>Tester</role>
+ </roles>
+ </operation>
+ <operation>
+ <name>list</name>
+ <roles>
+ <role>Tester</role>
+ <role>JBossAdmin</role>
+ </roles>
+ </operation>
+ </operations>
+ </authorization-target>
+ <authorization-target>
+ <name>jboss:service=invoker,*</name>
+ <operations>
+ <operation>
+ <name>setRMIObjectPort</name>
+ <roles>
+ <role>JBossAdmin</role>
+ </roles>
+ </operation>
+ <operation>
+ <name>get.*</name>
+ <roles>
+ <role>JBossAdmin</role>
+ <role>Tester</role>
+ <role>Babe</role>
+ </roles>
+ </operation>
+ </operations>
+ </authorization-target>
+ <authorization-target>
+ <name>jboss:*</name>
+ <operations>
+ <operation>
+ <!-- regex require . ... without it - dangling meta -->
+ <name>.*</name>
+ <roles>
+ <role>Tester</role>
+ </roles>
+ </operation>
+ <operation>
+ <name>get.*</name>
+ <roles>
+ <role>JBossAdmin</role>
+ <role>Babe</role>
+ </roles>
+ </operation>
+ </operations>
+ </authorization-target>
+</authorization-rules>
\ No newline at end of file
More information about the jboss-cvs-commits
mailing list