[jboss-cvs] JBossAS SVN: r61703 - in branches/JBoss_3_2_8_SP1_CP/varia/src: resources/jmx and 1 other directory.
jboss-cvs-commits at lists.jboss.org
jboss-cvs-commits at lists.jboss.org
Mon Mar 26 12:10:18 EDT 2007
Author: darran.lofthouse at jboss.com
Date: 2007-03-26 12:10:18 -0400 (Mon, 26 Mar 2007)
New Revision: 61703
Added:
branches/JBoss_3_2_8_SP1_CP/varia/src/main/org/jboss/jmx/adaptor/html/JMXOpsAccessControlFilter.java
Modified:
branches/JBoss_3_2_8_SP1_CP/varia/src/resources/jmx/jmx-console-web.xml
Log:
ASPATCH-172 - Access Control on JMX Operations in the JMX Console, including thread safety fix.
Copied: branches/JBoss_3_2_8_SP1_CP/varia/src/main/org/jboss/jmx/adaptor/html/JMXOpsAccessControlFilter.java (from rev 45754, branches/Branch_3_2/contrib/varia/src/main/org/jboss/jmx/adaptor/html/JMXOpsAccessControlFilter.java)
===================================================================
--- branches/JBoss_3_2_8_SP1_CP/varia/src/main/org/jboss/jmx/adaptor/html/JMXOpsAccessControlFilter.java (rev 0)
+++ branches/JBoss_3_2_8_SP1_CP/varia/src/main/org/jboss/jmx/adaptor/html/JMXOpsAccessControlFilter.java 2007-03-26 16:10:18 UTC (rev 61703)
@@ -0,0 +1,290 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2005, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt 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.jmx.adaptor.html;
+
+import java.io.IOException;
+import java.lang.reflect.Method;
+import java.security.Principal;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.List;
+import java.util.StringTokenizer;
+import javax.naming.InitialContext;
+
+import javax.security.auth.Subject;
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletResponse;
+
+import org.jboss.logging.Logger;
+import org.jboss.security.SimpleGroup;
+import org.jboss.security.SubjectSecurityManager;
+
+//$Id$
+
+/**
+ * JBAS-3311: Access Control on JMX Operations in the JMX Console.
+ * Filter that allows Role Based Authorization of the various
+ * JMX Operations. The actions that come as part of the request are:
+ * displayMBeans
+ * inspectMBean
+ * updateAttributes - Operations that involve updation of jmx attributes
+ * invokeOp - Operations that involve "invoke"
+ * invokeOpByName
+ * @author <a href="mailto:Anil.Saldhana at jboss.org">Anil Saldhana</a>
+ * @since Jun 12, 2006
+ * @version $Revision$
+ */
+public class JMXOpsAccessControlFilter implements Filter
+{
+ private static Logger log = Logger.getLogger(JMXOpsAccessControlFilter.class);
+ private boolean trace = log.isTraceEnabled();
+ private static final String ACTION_PARAM = "action";
+ private static final String DISPLAY_MBEANS_ACTION = "displayMBeans";
+ private static final String INSPECT_MBEAN_ACTION = "inspectMBean";
+ private static final String UPDATE_ATTRIBUTES_ACTION = "updateAttributes";
+ private static final String INVOKE_OP_ACTION = "invokeOp";
+ private static final String INVOKE_OP_BY_NAME_ACTION = "invokeOpByName";
+
+ private List updateAttributesRoles = null;
+ private List invokeOpRoles = null;
+ //Rare usecase
+ private List invokeMBeanRoles = null;
+
+ //An authorization delegate that the user can plug in which can do the
+ //authorization decisions - when deeper access control usecases arise
+ //The Authorization Delegate should have a method
+ //public Boolean authorize(ServletRequest,ServletResponse,List)
+ private Object authorizationDelegate = null;
+
+ /**
+ * @see Filter#init(javax.servlet.FilterConfig)
+ */
+ public void init(FilterConfig filterConfig) throws ServletException
+ {
+ String updateAttributesStr = filterConfig.getInitParameter("updateAttributes");
+ if(updateAttributesStr != null && updateAttributesStr.length() > 0)
+ updateAttributesRoles = this.getRoles(updateAttributesStr);
+
+ String invokeOpStr = filterConfig.getInitParameter("invokeOp");
+ if(invokeOpStr != null && invokeOpStr.length() > 0)
+ invokeOpRoles = this.getRoles(invokeOpStr);
+
+ String inspectMBeanStr = filterConfig.getInitParameter("inspectMBean");
+ if(inspectMBeanStr != null && inspectMBeanStr.length() > 0)
+ invokeMBeanRoles = this.getRoles(inspectMBeanStr);
+
+ //Optional - Authorization Delegate
+ String delegateStr = filterConfig.getInitParameter("authorizationDelegate");
+ if(delegateStr != null && delegateStr.length() > 0)
+ authorizationDelegate = this.instantiate(delegateStr);
+ }
+
+ /**
+ * @see Filter#doFilter(javax.servlet.ServletRequest,
+ * javax.servlet.ServletResponse, javax.servlet.FilterChain)
+ */
+ public void doFilter(ServletRequest request, ServletResponse response,
+ FilterChain chain)
+ throws IOException, ServletException
+ {
+ boolean passThrough = true;
+
+ String action = request.getParameter(ACTION_PARAM);
+
+ if( action == null )
+ action = DISPLAY_MBEANS_ACTION;
+
+ if( action.equals(UPDATE_ATTRIBUTES_ACTION))
+ passThrough = authorize(request, response, updateAttributesRoles);
+ else if( action.equals(INVOKE_OP_ACTION) || action.equals(INVOKE_OP_BY_NAME_ACTION))
+ passThrough = authorize(request, response,invokeOpRoles);
+ else if( action.equals(INSPECT_MBEAN_ACTION))
+ passThrough = authorize(request, response,invokeMBeanRoles);
+
+ if(!passThrough)
+ ((HttpServletResponse)response).setStatus(HttpServletResponse.SC_FORBIDDEN);
+ else
+ chain.doFilter(request, response);
+ }
+
+ /**
+ * @see Filter#destroy()
+ */
+ public void destroy()
+ {
+ }
+
+ /**
+ * Authorize the JMX Operations
+ * If there is an Authorization Delegate plugged in, it will
+ * be consulted for access control
+ * @param request
+ * @param response
+ * @param listToCheck
+ * @return
+ */
+ private boolean authorize(ServletRequest request,
+ ServletResponse response, List listToCheck)
+ {
+ //Check if there is an authorization delegate
+ if(authorizationDelegate != null)
+ return checkWithDelegate(request,response,listToCheck);
+
+ if(listToCheck == null || listToCheck.size() == 0)
+ return true;
+
+ ArrayList subjectRoles = getSubjectRoles();
+
+ boolean result = false;
+ int len = subjectRoles.size();
+ for(int i = 0; i < len; i++)
+ {
+ String subjectRole = (String)subjectRoles.get(i);
+ result = listToCheck.contains(subjectRole);
+ if(result)
+ break;
+ }
+ return result;
+ }
+
+ private boolean checkWithDelegate(ServletRequest request,
+ ServletResponse response, List listToCheck)
+ {
+ Boolean result = Boolean.FALSE;
+ String name = "authorize";
+ Class[] args = new Class[] {ServletRequest.class, ServletResponse.class,
+ List.class};
+ try
+ {
+ Method meth = authorizationDelegate.getClass().getMethod(name,args);
+ result = (Boolean)meth.invoke(authorizationDelegate,
+ new Object[]{request,response,listToCheck});
+ }
+ catch ( Exception e)
+ {
+ if(trace)
+ log.error("Error invoking AuthorizationDelegate:",e);
+ }
+ return result.booleanValue();
+ }
+
+
+ /**
+ * Get a list of roles from the string that is comma-delimited
+ * @param commaSeperatedRoles
+ * @return
+ */
+ private List getRoles(String commaSeperatedRoles)
+ {
+ StringTokenizer st = new StringTokenizer(commaSeperatedRoles,",");
+ int numTokens = st.countTokens();
+ String[] strArr = new String[numTokens];
+ for(int i=0; i < numTokens; i++)
+ {
+ strArr[i] = st.nextToken();
+ }
+ return Arrays.asList(strArr);
+ }
+
+ /**
+ * Get a list of roles from the authenticated subject
+ * @return
+ */
+ private ArrayList getSubjectRoles()
+ {
+ ArrayList alist = new ArrayList();
+
+ try
+ {
+ Subject caller = getActiveSubject();
+ Iterator iter = caller.getPrincipals().iterator();
+ while(iter != null && iter.hasNext())
+ {
+ Principal p = (Principal)iter.next();
+ if(p instanceof SimpleGroup)
+ {
+ SimpleGroup sg = (SimpleGroup)p;
+ String name = sg.getName();
+ if("Roles".equals(name))
+ {
+ Enumeration en = sg.members();
+ while(en.hasMoreElements())
+ {
+ String role = en.nextElement().toString();
+ if(role != null)
+ alist.add(role);
+ }
+ }
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ if(trace)
+ log.trace("Error obtaining authenticated subject:",e);
+ }
+ if(trace)
+ log.trace("Subject Roles="+alist);
+ return alist;
+ }
+
+
+ /**
+ * Instantiate The Authorization Delegate
+ * @param delegateStr
+ * @return
+ */
+ public Object instantiate(String delegateStr)
+ {
+ ClassLoader cl = Thread.currentThread().getContextClassLoader();
+ Object obj = null;
+ try
+ {
+ Class clazz = cl.loadClass(delegateStr);
+ obj = clazz.newInstance();
+ }
+ catch (Exception e)
+ {
+ if(trace)
+ log.error("Error instantiating AuthorizationDelegate:",e);
+ }
+ return obj;
+ }
+
+ /**
+ * Get the current authenticated subject
+ */
+ private Subject getActiveSubject() throws Exception
+ {
+ InitialContext ctx = new InitialContext();
+ SubjectSecurityManager mgr = (SubjectSecurityManager)ctx.lookup("java:comp/env/security/securityMgr");
+ Subject sub = mgr.getActiveSubject();
+ return sub;
+ }
+}
Modified: branches/JBoss_3_2_8_SP1_CP/varia/src/resources/jmx/jmx-console-web.xml
===================================================================
--- branches/JBoss_3_2_8_SP1_CP/varia/src/resources/jmx/jmx-console-web.xml 2007-03-26 16:00:22 UTC (rev 61702)
+++ branches/JBoss_3_2_8_SP1_CP/varia/src/resources/jmx/jmx-console-web.xml 2007-03-26 16:10:18 UTC (rev 61703)
@@ -5,6 +5,26 @@
<web-app>
<description>The standard web descriptor for the html adaptor</description>
+ <!--
+ <filter>
+ <filter-name>JmxOpsAccessControlFilter</filter-name>
+ <filter-class>org.jboss.jmx.adaptor.html.JMXOpsAccessControlFilter</filter-class>
+ <init-param>
+ <param-name>updateAttributes</param-name>
+ <param-value>UpdateAttributeRole</param-value>
+ <description>Comma-delimited Roles that define the JMX Operation denoting updation of Attributes</description>
+ </init-param>
+ <init-param>
+ <param-name>invokeOp</param-name>
+ <param-value>InvokeOpRole</param-value>
+ <description>Comma-delimited Roles that define the JMX Operation denoting Invocation of Operations</description>
+ </init-param>
+ </filter>
+ <filter-mapping>
+ <filter-name>JmxOpsAccessControlFilter</filter-name>
+ <servlet-name>HtmlAdaptor</servlet-name>
+ </filter-mapping>
+ -->
<servlet>
<servlet-name>HtmlAdaptor</servlet-name>
<servlet-class>org.jboss.jmx.adaptor.html.HtmlAdaptorServlet</servlet-class>
More information about the jboss-cvs-commits
mailing list