[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