ASF Bugzilla – Attachment 30805 Details for
Bug 55477
Add a solution to map a realm name to a security role
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
MappingRealm incl. docs
MappingRealm.v3.patch (text/plain), 17.36 KB, created by
Stefan Mayr
on 2013-09-08 09:56:52 UTC
(
hide
)
Description:
MappingRealm incl. docs
Filename:
MIME Type:
Creator:
Stefan Mayr
Created:
2013-09-08 09:56:52 UTC
Size:
17.36 KB
patch
obsolete
>Index: java/org/apache/catalina/realm/LocalStrings.properties >=================================================================== >--- java/org/apache/catalina/realm/LocalStrings.properties (Revision 1520848) >+++ java/org/apache/catalina/realm/LocalStrings.properties (Arbeitskopie) >@@ -58,6 +58,12 @@ > jndiRealm.exception=Exception performing authentication > jndiRealm.exception.retry=Exception performing authentication. Retrying... > jndiRealm.open=Exception opening directory server connection >+mappingRealm.fileNotExists=Realm mapping file {0} does not exist. No security role will be available >+mappingRealm.invalidMapping=Invalid syntax in mapping [{0}] >+mappingRealm.loadFailed=Could not Realm mapping file {0} >+mappingRealm.loadOK=Loaded Realm mapping file {0} >+mappingRealm.loadRoleMappings=Load role mappings from configuration, ignore {0} >+mappingRealm.mapped=Mapped application security role [{0}] to realm security role [{1}] > memoryRealm.authenticateFailure=Username {0} NOT successfully authenticated > memoryRealm.authenticateSuccess=Username {0} successfully authenticated > memoryRealm.loadExist=Memory database file {0} cannot be read >Index: java/org/apache/catalina/realm/MappingRealm.java >=================================================================== >--- java/org/apache/catalina/realm/MappingRealm.java (Revision 0) >+++ java/org/apache/catalina/realm/MappingRealm.java (Arbeitskopie) >@@ -0,0 +1,306 @@ >+/* >+ * 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.catalina.realm; >+ >+import java.security.Principal; >+import java.util.Properties; >+import java.io.IOException; >+import java.io.File; >+import java.io.FileInputStream; >+ >+import org.apache.catalina.Globals; >+import org.apache.catalina.Wrapper; >+import org.apache.catalina.LifecycleException; >+import org.apache.juli.logging.Log; >+import org.apache.juli.logging.LogFactory; >+ >+/** >+ * This class extends the CombinedRealm (hence it can wrap other Realms) to >+ * map application security roles to different realm roles. This is useful >+ * when you cannot change applications to match your internal role names. >+ * This implementation of <b>Realm</b> reads a properties file to configure >+ * the mapping of roles. >+ * >+ * <strong>IMPLEMENTATION NOTE</strong>: It is assumed that the in-memory >+ * collection representing our role mappings is initialized at application >+ * startup and never modified again. Therefore, no thread synchronization is >+ * performed around accesses to the mappings collection. >+ * >+ * @author Stefan Mayr >+ * @version $Id$ >+ */ >+ >+public class MappingRealm extends CombinedRealm { >+ >+ private static final Log log = LogFactory.getLog(MappingRealm.class); >+ >+ >+ // ----------------------------------------------------- Instance Variables >+ >+ /** >+ * Internal security role translation >+ */ >+ protected Properties mapping = null; >+ >+ /** >+ * The pathname (absolute or relative to Catalina's current working >+ * directory) of the properties file containing the role mapping. >+ */ >+ protected String pathname = "conf/mapping.properties"; >+ >+ /** >+ * Regular expression describing the symbol or string used as assignment >+ * operator when using roleMappings. Defaults to "=". >+ */ >+ protected String assignment = "="; >+ >+ /** >+ * Regular expression describing the symbol or string used as separator >+ * between different assignments when using roleMappings. Defaults to ";". >+ */ >+ protected String separator = ";"; >+ >+ /** >+ * String with role mappings. If this is set the properties file is >+ * ignored. Uses the assignment and separator variables to split the >+ * string into single role mappings. >+ */ >+ protected String roleMappings = null; >+ >+ /** >+ * Descriptive information about this Realm implementation. >+ */ >+ protected static final String info = >+ "org.apache.catalina.realm.MappingRealm/1.0"; >+ >+ /** >+ * Descriptive information about this Realm implementation. >+ */ >+ protected static final String name = "MappingRealm"; >+ >+ /** >+ * Return descriptive information about this Realm implementation and >+ * the corresponding version number, in the format >+ * <code><description>/<version></code>. >+ */ >+ @Override >+ public String getInfo() { >+ >+ return info; >+ >+ } >+ >+ /** >+ * Return a short name for this Realm implementation. >+ */ >+ @Override >+ protected String getName() { >+ >+ return (name); >+ >+ } >+ >+ /** >+ * Get assignment string >+ */ >+ public String getAssignment() { >+ return assignment; >+ } >+ >+ /** >+ * Set assignment string >+ * >+ * @param assignment Regular expression to split application security role >+ * name from the realm role name in the mapping string >+ */ >+ public void setAssignment(String assignment) { >+ this.assignment=assignment; >+ } >+ >+ /** >+ * Get pathname of mapping properties files >+ */ >+ public String getPathname() { >+ return pathname; >+ } >+ >+ /** >+ * Set the pathname of our properties file containing role mappings. >+ * If a relative pathname is specified, it is resolved against >+ * "catalina.base". >+ * >+ * @param pathname The new pathname >+ */ >+ public void setPathname(String pathname) { >+ this.pathname = pathname; >+ } >+ >+ /** >+ * Get mapping rule string >+ */ >+ public String getRoleMappings() { >+ return roleMappings; >+ } >+ >+ /** >+ * Set the role mappings as string. The string is split into parts using >+ * the assignment and separator variables. If this string is set the >+ * properties file in pathname is ignored. >+ * >+ * @param roleMappings String of role mappings >+ */ >+ public void setRoleMappings(String roleMappings) { >+ this.roleMappings=roleMappings; >+ } >+ >+ /** >+ * Get separator string >+ */ >+ public String getSeparator() { >+ return separator; >+ } >+ >+ /** >+ * Set separator string >+ * >+ * @param separator Regular expression to split the roles in the mapping >+ * string >+ */ >+ public void setSeparator(String separator) { >+ this.separator=separator; >+ } >+ >+ // ---------------------------------------------------------- Realm Methods >+ >+ /** >+ * Return <code>true</code> if the specified Principal has the specified >+ * security role, within the context of this Realm; otherwise return >+ * <code>false</code>. This method can be overridden by Realm >+ * implementations, but the default is adequate when an instance of >+ * <code>GenericPrincipal</code> is used to represent authenticated >+ * Principals from this Realm. >+ * >+ * @param principal Principal for whom the role is to be checked >+ * @param role Security role to be checked >+ */ >+ @Override >+ public boolean hasRole(Wrapper wrapper, Principal principal, String role) { >+ >+ // Copied from GenericPrincipal >+ if("*".equals(role)) { // Special 2.4 role meaning everyone >+ return true; >+ } >+ if (role == null) { >+ return (false); >+ } >+ >+ String mappedRole = mapping.getProperty(role); >+ >+ if((mappedRole != null) && super.hasRole(wrapper, principal, mappedRole)) { >+ if (log.isDebugEnabled()) { >+ log.debug(sm.getString("mappingRealm.mapped", role, mappedRole)); >+ } >+ return true; >+ } else { >+ return false; >+ } >+ } >+ >+ >+ // ------------------------------------------------------ Lifecycle Methods >+ >+ >+ /** >+ * Prepare for the beginning of active use of the public methods of this >+ * component and implement the requirements of >+ * {@link org.apache.catalina.util.LifecycleBase#startInternal()}. >+ * >+ * @exception LifecycleException if this component detects a fatal error >+ * that prevents this component from being used >+ */ >+ @Override >+ protected void startInternal() throws LifecycleException { >+ >+ mapping = new Properties(); >+ >+ if (roleMappings != null) { >+ log.info(sm.getString("mappingRealm.loadRoleMappings",pathname)); >+ for (String entry : roleMappings.split(separator)) { >+ String[] kv = entry.split(assignment, 2); >+ if (kv.length == 2) { >+ mapping.setProperty(kv[0], kv[1]); >+ } else { >+ log.error( >+ sm.getString("mappingRealm.invalidMapping",entry) >+ ); >+ } >+ } >+ } else { >+ File file = new File(pathname); >+ if (!file.isAbsolute()) { >+ file = new File(System.getProperty(Globals.CATALINA_BASE_PROP), >+ pathname); >+ } >+ if (file.exists()) { >+ FileInputStream fis = null; >+ try { >+ fis = new FileInputStream(file); >+ mapping.load(fis); >+ log.info(sm.getString("mappingRealm.loadOK", pathname)); >+ } catch (IOException ioe) { >+ log.error(sm.getString("mappingRealm.loadFailed", >+ pathname)); >+ } finally { >+ if (fis != null) { >+ try { >+ fis.close(); >+ } catch (IOException ioe) { >+ // Ignore >+ } >+ } >+ } >+ } else { >+ log.error(sm.getString("mappingRealm.fileNotExists", >+ pathname)); >+ } >+ } >+ >+ super.startInternal(); >+ } >+ >+ >+ /** >+ * Gracefully terminate the active use of the public methods of this >+ * component and implement the requirements of >+ * {@link org.apache.catalina.util.LifecycleBase#stopInternal()}. >+ * >+ * @exception LifecycleException if this component detects a fatal error >+ * that needs to be reported >+ */ >+ @Override >+ protected void stopInternal() throws LifecycleException { >+ >+ // Perform normal superclass finalization >+ super.stopInternal(); >+ >+ // Release mappings >+ mapping = null; >+ roleMappings = null; >+ } >+} >+ >Index: webapps/docs/config/realm.xml >=================================================================== >--- webapps/docs/config/realm.xml (Revision 1520848) >+++ webapps/docs/config/realm.xml (Arbeitskopie) >@@ -24,6 +24,7 @@ > > <properties> > <author email="craigmcc@apache.org">Craig R. McClanahan</author> >+ <author>Stefan Mayr</author> > <title>The Realm Component</title> > </properties> > >@@ -979,7 +980,58 @@ > using the LockOutRealm component.</p> > > </subsection> >+ >+ <subsection name="Mapping Realm - org.apache.catalina.realm.MappingRealm"> >+ >+ <p><strong>Mapping Realm</strong> is an implementation of the Tomcat >+ <code>Realm</code> interface that extends the CombinedRealm to map >+ application security roles to different realm roles. This is useful >+ when you cannot change applications to match your internal role names. >+ This implementation of <b>Realm</b> reads a properties file to configure >+ the mapping of roles.</p> > >+ <p>This Realm does not require modification to the underlying Realms or the >+ associated user storage mechanisms. It is limited to translate application >+ security roles to realm roles using the given mappings. Roles that are not >+ defined in the mappings are NOT passed to sub-realms.</p> >+ >+ <p>Sub-realms are defined by nesting <code>Realm</code> elements inside the >+ <code>Realm</code> element that defines the MappingRealm. Authentication >+ will be attempted against each <code>Realm</code> in the order they are >+ listed. Authentication against any Realm will be sufficient to authenticate >+ the user.</p> >+ >+ <p>The Mapping Realm implementation supports the following >+ additional attributes:</p> >+ >+ <attributes> >+ <attribute name="assignment" required="false"> >+ <p>Regular expression to split application security role name from the >+ realm role name in the roleMapping string. >+ If no assignment is specified, the default value is <code>=</code>.</p> >+ </attribute> >+ <attribute name="pathname" required="false"> >+ <p>Absolute or relative (to $CATALINA_BASE) pathname to the properties >+ file containing our role mappings. If no pathname is specified, the >+ default value is <code>conf/mapping.properties</code>.</p> >+ </attribute> >+ <attribute name="roleMappings" required="false"> >+ <p>Inline declaration of role mappings. If this is specified the >+ properties file in pathname is ignored. The string is split into >+ multiple role mappings using the assignment and separator attributes. >+ </p> >+ </attribute> >+ <attribute name="separator" required="false"> >+ <p>Regular expression to split the roles in the roleMapping string. >+ If no separator is specified, the default value is <code>;</code>.</p> >+ </attribute> >+ </attributes> >+ >+ <p>See the <a href="../realm-howto.html">Container-Managed Security >+ Guide</a> for more information on setting up container managed security >+ using the MappingRealm component.</p> >+ </subsection> >+ > </section> > > >Index: webapps/docs/realm-howto.xml >=================================================================== >--- webapps/docs/realm-howto.xml (Revision 1520848) >+++ webapps/docs/realm-howto.xml (Arbeitskopie) >@@ -26,6 +26,7 @@ > <author email="craigmcc@apache.org">Craig R. McClanahan</author> > <author email="yoavs@apache.org">Yoav Shapira</author> > <author email="arjaquith@mindspring.com">Andrew R. Jaquith</author> >+ <author>Stefan Mayr</author> > <title>Realm Configuration HOW-TO</title> > </properties> > >@@ -1215,6 +1216,72 @@ > > </subsection> > >+<subsection name="MappingRealm"> >+ >+ <h3>Introduction</h3> >+ >+ <p><strong>Mapping Realm</strong> is an implementation of the Tomcat >+ <code>Realm</code> interface that extends the CombinedRealm to map >+ application security roles to different realm roles. This is useful >+ when you cannot change applications to match your internal role names. >+ This implementation of <b>Realm</b> reads a properties file to configure >+ the mapping of roles.</p> >+ >+ <p>This Realm does not require modification to the underlying Realms or the >+ associated user storage mechanisms. It is limited to translate application >+ security roles to realm roles using the given mappings. Roles that are not >+ defined in the mappings are NOT passed to sub-realms.</p> >+ >+ <p>Sub-realms are defined by nesting <code>Realm</code> elements inside the >+ <code>Realm</code> element that defines the MappingRealm. Authentication >+ will be attempted against each <code>Realm</code> in the order they are >+ listed. Authentication against any Realm will be sufficient to authenticate >+ the user.</p> >+ >+ <h3>Realm Element Attributes</h3> >+ <p>To configure a MappingRealm, you create a <code><Realm></code> >+ element and nest it in your <code>$CATALINA_BASE/conf/server.xml</code> >+ file within your <code><Engine></code> or <code><Host></code>. >+ You can also nest inside a <code><Context></code> node in a >+ <code>context.xml</code> file. The attributes for the >+ MappingRealm are defined in the <a href="config/realm.html">Realm</a> >+ configuration documentation.</p> >+ >+<h3>Example using mapping.properties</h3> >+ >+<p>Here is an example of how your server.xml snippet should look to add mapping >+functionality to a UserDatabase Realm.</p> >+ >+<source> >+<Realm className="org.apache.catalina.realm.MappingRealm" > >+ <Realm className="org.apache.catalina.realm.UserDatabaseRealm" >+ resourceName="UserDatabase"/> >+</Realm> >+</source> >+ >+<p>Here is an example of how your <code>conf/mapping.properties</code> snippet >+should look to add map the manager-gui role from Tomcat Manager to the example >+tomcat role in the default UserDatabase Realm configuration in >+<code>conf/tomcat-users.xml</code>.</p> >+ >+<source> >+manager-gui=tomcat >+</source> >+ >+<h3>Example using inline configuration</h3> >+ >+<p>Here is an example of how your server.xml snippet should look if you use >+inline configuration and ignore the properties file</p> >+ >+<source> >+<Realm className="org.apache.catalina.realm.MappingRealm" roleMappings="manager-gui=tomcat"> >+ <Realm className="org.apache.catalina.realm.UserDatabaseRealm" >+ resourceName="UserDatabase"/> >+</Realm> >+</source> >+ >+</subsection> >+ > </section> > > </body>
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 55477
:
30759
|
30788
| 30805