View Javadoc

1   /* 
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *     http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.jetspeed.security.impl;
18  
19  import java.security.Principal;
20  import java.util.ArrayList;
21  import java.util.Collection;
22  import java.util.Iterator;
23  import java.util.LinkedList;
24  import java.util.List;
25  import java.util.Set;
26  import java.util.prefs.BackingStoreException;
27  import java.util.prefs.Preferences;
28  
29  import org.apache.commons.logging.Log;
30  import org.apache.commons.logging.LogFactory;
31  import org.apache.jetspeed.i18n.KeyedMessage;
32  import org.apache.jetspeed.security.AuthenticationProviderProxy;
33  import org.apache.jetspeed.security.Role;
34  import org.apache.jetspeed.security.RoleManager;
35  import org.apache.jetspeed.security.RolePrincipal;
36  import org.apache.jetspeed.security.SecurityException;
37  import org.apache.jetspeed.security.SecurityProvider;
38  import org.apache.jetspeed.security.spi.RoleSecurityHandler;
39  import org.apache.jetspeed.security.spi.SecurityMappingHandler;
40  import org.apache.jetspeed.util.ArgUtil;
41  
42  /***
43   * <p>
44   * Implementation for managing roles.
45   * </p>
46   * <p>
47   * Role hierarchy elements are being returned as a {@link Role}collection. The
48   * backing implementation must appropriately map the role hierarchy to a
49   * preferences sub-tree.
50   * </p>
51   * <p>
52   * The convention {principal}.{subprincipal} has been chosen to name roles
53   * hierachies in order to support declarative security. Implementation follow
54   * the conventions enforced by the {@link Preferences}API.
55   * </p>
56   * 
57   * @author <a href="mailto:dlestrat@apache.org">David Le Strat </a>
58   * @author <a href="mailto:taylor@apache.org">David Sean Taylor </a>
59   */
60  public class RoleManagerImpl implements RoleManager
61  {
62      /*** The logger. */
63      private static final Log log = LogFactory.getLog(RoleManagerImpl.class);
64  
65      /*** The authentication provider proxy. */
66      private AuthenticationProviderProxy atnProviderProxy = null;
67      
68      /*** The role security handler. */
69      private RoleSecurityHandler roleSecurityHandler = null;
70  
71      /*** The security mapping handler. */
72      private SecurityMappingHandler securityMappingHandler = null;
73  
74      /***
75       * @param securityProvider The security provider.
76       */
77      public RoleManagerImpl(SecurityProvider securityProvider)
78      {
79          this.atnProviderProxy = securityProvider.getAuthenticationProviderProxy();
80          this.roleSecurityHandler = securityProvider.getRoleSecurityHandler();
81          this.securityMappingHandler = securityProvider.getSecurityMappingHandler();
82      }
83  
84      /***
85       * @see org.apache.jetspeed.security.RoleManager#addRole(java.lang.String)
86       */
87      public void addRole(String roleFullPathName) throws SecurityException
88      {
89          ArgUtil.notNull(new Object[] { roleFullPathName }, new String[] { "roleFullPathName" },
90                  "addRole(java.lang.String)");
91  
92          // Check if role already exists.
93          if (roleExists(roleFullPathName))
94          {
95              throw new SecurityException(SecurityException.ROLE_ALREADY_EXISTS.create(roleFullPathName));
96          }
97  
98          RolePrincipal rolePrincipal = new RolePrincipalImpl(roleFullPathName);
99          String fullPath = rolePrincipal.getFullPath();
100         // Add the preferences.
101         Preferences preferences = Preferences.userRoot().node(fullPath);
102         if (log.isDebugEnabled())
103         {
104             log.debug("Added role preferences node: " + fullPath);
105         }
106         try
107         {
108             if ((null != preferences) && preferences.absolutePath().equals(fullPath))
109             {
110                 // Add role principal.
111                 roleSecurityHandler.setRolePrincipal(rolePrincipal);
112                 if (log.isDebugEnabled())
113                 {
114                     log.debug("Added role: " + fullPath);
115                 }
116             }
117         }
118         catch (SecurityException se)
119         {
120             KeyedMessage msg = 
121                 SecurityException.UNEXPECTED.create("RoleManager.addRole",
122                                                     "RoleSecurityHandler.setRolePrincipal("+rolePrincipal.getName()+")",
123                                                     se.getMessage());
124             log.error(msg, se);
125 
126             // Remove the preferences node.
127             try
128             {
129                 preferences.removeNode();
130             }
131             catch (BackingStoreException bse)
132             {
133                 bse.printStackTrace();
134             }
135             throw new SecurityException(msg, se);
136         }
137     }
138 
139     /***
140      * @see org.apache.jetspeed.security.RoleManager#removeRole(java.lang.String)
141      */
142     public void removeRole(String roleFullPathName) throws SecurityException
143     {
144         ArgUtil.notNull(new Object[] { roleFullPathName }, new String[] { "roleFullPathName" },
145                 "removeRole(java.lang.String)");
146 
147         // Resolve the role hierarchy.
148         Preferences prefs = Preferences.userRoot().node(
149                 RolePrincipalImpl.getFullPathFromPrincipalName(roleFullPathName));
150         String[] roles = securityMappingHandler.getRoleHierarchyResolver().resolveChildren(prefs);
151         for (int i = 0; i < roles.length; i++)
152         {
153             try
154             {
155                 roleSecurityHandler.removeRolePrincipal(new RolePrincipalImpl(RolePrincipalImpl
156                         .getPrincipalNameFromFullPath(roles[i])));
157             }
158             catch (Exception e)
159             {
160                 KeyedMessage msg = 
161                     SecurityException.UNEXPECTED.create("RoleManager.removeRole",
162                                                         "RoleSecurityHandler.removeRolePrincipal("+RolePrincipalImpl.getPrincipalNameFromFullPath(roles[i])+")",
163                                                         e.getMessage());
164                 log.error(msg, e);
165                 throw new SecurityException(msg, e);
166             }
167             // Remove preferences
168             Preferences rolePref = Preferences.userRoot().node(roles[i]);
169             try
170             {
171                 rolePref.removeNode();
172             }
173             catch (BackingStoreException bse)
174             {
175                 KeyedMessage msg = 
176                     SecurityException.UNEXPECTED.create("RoleManager.removeRole",
177                                                         "Preferences.removeNode("+roles[i]+")",
178                                                         bse.getMessage());
179                 log.error(msg, bse);
180                 throw new SecurityException(msg, bse);
181             }
182         }
183     }
184 
185     /***
186      * @see org.apache.jetspeed.security.RoleManager#roleExists(java.lang.String)
187      */
188     public boolean roleExists(String roleFullPathName)
189     {
190         ArgUtil.notNull(new Object[] { roleFullPathName }, new String[] { "roleFullPathName" },
191                 "roleExists(java.lang.String)");
192 
193         Principal principal = roleSecurityHandler.getRolePrincipal(roleFullPathName);
194         boolean roleExists = (null != principal);
195         if (log.isDebugEnabled())
196         {
197             log.debug("Role exists: " + roleExists);
198             log.debug("Role: " + roleFullPathName);
199         }
200         return roleExists;
201     }
202 
203     /***
204      * @see org.apache.jetspeed.security.RoleManager#getRole(java.lang.String)
205      */
206     public Role getRole(String roleFullPathName) throws SecurityException
207     {
208         ArgUtil.notNull(new Object[] { roleFullPathName }, new String[] { "roleFullPathName" },
209                 "getRole(java.lang.String)");
210 
211         String fullPath = RolePrincipalImpl.getFullPathFromPrincipalName(roleFullPathName);
212 
213         Principal rolePrincipal = roleSecurityHandler.getRolePrincipal(roleFullPathName);
214         if (null == rolePrincipal)
215         {
216             throw new SecurityException(SecurityException.ROLE_DOES_NOT_EXIST.create(roleFullPathName));
217         }
218         Preferences preferences = Preferences.userRoot().node(fullPath);
219         Role role = new RoleImpl(rolePrincipal, preferences);
220         return role;
221     }
222 
223     /***
224      * @see org.apache.jetspeed.security.RoleManager#getRolesForUser(java.lang.String)
225      */
226     public Collection getRolesForUser(String username) throws SecurityException
227     {
228         ArgUtil.notNull(new Object[] { username }, new String[] { "username" }, "getRolesForUser(java.lang.String)");
229 
230         Collection roles = new ArrayList();
231 
232         Set rolePrincipals = securityMappingHandler.getRolePrincipals(username);
233         Iterator rolePrincipalsIter = rolePrincipals.iterator();
234         while (rolePrincipalsIter.hasNext())
235         {
236             Principal rolePrincipal = (Principal) rolePrincipalsIter.next();
237             Preferences preferences = Preferences.userRoot().node(
238                     RolePrincipalImpl.getFullPathFromPrincipalName(rolePrincipal.getName()));
239             roles.add(new RoleImpl(rolePrincipal, preferences));
240         }
241         return roles;
242     }
243 
244     /***
245      * @see org.apache.jetspeed.security.RoleManager#getRolesInGroup(java.lang.String)
246      */
247     public Collection getRolesInGroup(String groupFullPathName) throws SecurityException
248     {
249         ArgUtil.notNull(new Object[] { groupFullPathName }, new String[] { "groupFullPathName" },
250                 "getRolesInGroup(java.lang.String)");
251 
252         Collection roles = new ArrayList();
253 
254         Set rolePrincipals = securityMappingHandler.getRolePrincipalsInGroup(groupFullPathName);
255         Iterator rolePrincipalsIter = rolePrincipals.iterator();
256         while (rolePrincipalsIter.hasNext())
257         {
258             Principal rolePrincipal = (Principal) rolePrincipalsIter.next();
259             Preferences preferences = Preferences.userRoot().node(
260                     RolePrincipalImpl.getFullPathFromPrincipalName(rolePrincipal.getName()));
261             roles.add(new RoleImpl(rolePrincipal, preferences));
262         }
263         return roles;
264     }
265 
266     /***
267      * @see org.apache.jetspeed.security.RoleManager#addRoleToUser(java.lang.String,
268      *      java.lang.String)
269      */
270     public void addRoleToUser(String username, String roleFullPathName) throws SecurityException
271     {
272         ArgUtil.notNull(new Object[] { username, roleFullPathName }, new String[] { "username", "roleFullPathName" },
273                 "addUserToRole(java.lang.String, java.lang.String)");
274 
275         // Get the role principal to add to user.
276         Principal rolePrincipal = roleSecurityHandler.getRolePrincipal(roleFullPathName);
277         if (null == rolePrincipal)
278         {
279             throw new SecurityException(SecurityException.ROLE_DOES_NOT_EXIST.create(roleFullPathName));
280         }
281         // Check that user exists.
282         Principal userPrincipal = atnProviderProxy.getUserPrincipal(username);
283         if (null == userPrincipal)
284         {
285             throw new SecurityException(SecurityException.USER_DOES_NOT_EXIST.create(username));
286         }
287         // Get the user roles.
288         Set rolePrincipals = securityMappingHandler.getRolePrincipals(username);
289         // Add role to user.
290         if (!rolePrincipals.contains(rolePrincipal))
291         {
292             securityMappingHandler.setUserPrincipalInRole(username, roleFullPathName);
293         }
294     }
295 
296     /***
297      * @see org.apache.jetspeed.security.RoleManager#removeRoleFromUser(java.lang.String,
298      *      java.lang.String)
299      */
300     public void removeRoleFromUser(String username, String roleFullPathName) throws SecurityException
301     {
302         ArgUtil.notNull(new Object[] { username, roleFullPathName }, new String[] { "username", "roleFullPathName" },
303                 "removeRoleFromUser(java.lang.String, java.lang.String)");
304 
305         // Check that user exists.
306         Principal userPrincipal = atnProviderProxy.getUserPrincipal(username);
307         if (null == userPrincipal)
308         {
309             throw new SecurityException(SecurityException.USER_DOES_NOT_EXIST.create(username));
310         }
311         // Get the role principal to remove.
312         Principal rolePrincipal = roleSecurityHandler.getRolePrincipal(roleFullPathName);
313         if (null != rolePrincipal)
314         {
315             securityMappingHandler.removeUserPrincipalInRole(username, roleFullPathName);
316         }
317     }
318 
319     /***
320      * @see org.apache.jetspeed.security.RoleManager#isUserInRole(java.lang.String,
321      *      java.lang.String)
322      */
323     public boolean isUserInRole(String username, String roleFullPathName) throws SecurityException
324     {
325         ArgUtil.notNull(new Object[] { username, roleFullPathName }, new String[] { "username", "roleFullPathName" },
326                 "isUserInRole(java.lang.String, java.lang.String)");
327 
328         boolean isUserInRole = false;
329 
330         Set rolePrincipals = securityMappingHandler.getRolePrincipals(username);
331         Principal rolePrincipal = new RolePrincipalImpl(roleFullPathName);
332         if (rolePrincipals.contains(rolePrincipal))
333         {
334             isUserInRole = true;
335         }
336         return isUserInRole;
337     }
338 
339     /***
340      * @see org.apache.jetspeed.security.RoleManager#addRoleToGroup(java.lang.String,
341      *      java.lang.String)
342      */
343     public void addRoleToGroup(String roleFullPathName, String groupFullPathName) throws SecurityException
344     {
345         ArgUtil.notNull(new Object[] { roleFullPathName, groupFullPathName }, new String[] { "roleFullPathName",
346                 "groupFullPathName" }, "addRoleToGroup(java.lang.String, java.lang.String)");
347 
348         // Get the role principal to add to group.
349         Principal rolePrincipal = roleSecurityHandler.getRolePrincipal(roleFullPathName);
350         if (null == rolePrincipal)
351         {
352             throw new SecurityException(SecurityException.ROLE_DOES_NOT_EXIST.create(roleFullPathName));
353         }
354         securityMappingHandler.setRolePrincipalInGroup(groupFullPathName, roleFullPathName);
355     }
356 
357     /***
358      * @see org.apache.jetspeed.security.RoleManager#removeRoleFromGroup(java.lang.String,
359      *      java.lang.String)
360      */
361     public void removeRoleFromGroup(String roleFullPathName, String groupFullPathName) throws SecurityException
362     {
363         ArgUtil.notNull(new Object[] { roleFullPathName, groupFullPathName }, new String[] { "roleFullPathName",
364                 "groupFullPathName" }, "removeRoleFromGroup(java.lang.String, java.lang.String)");
365         
366         // Get the role principal to remove.
367         Principal rolePrincipal = roleSecurityHandler.getRolePrincipal(roleFullPathName);
368         if (null != rolePrincipal)
369         {
370             securityMappingHandler.removeRolePrincipalInGroup(groupFullPathName, roleFullPathName);
371         }
372     }
373 
374     /***
375      * @see org.apache.jetspeed.security.RoleManager#isGroupInRole(java.lang.String,
376      *      java.lang.String)
377      */
378     public boolean isGroupInRole(String groupFullPathName, String roleFullPathName) throws SecurityException
379     {
380         ArgUtil.notNull(new Object[] { roleFullPathName, groupFullPathName }, new String[] { "roleFullPathName",
381                 "groupFullPathName" }, "isGroupInRole(java.lang.String, java.lang.String)");
382 
383         boolean isGroupInRole = false;
384 
385         Set rolePrincipals = securityMappingHandler.getRolePrincipalsInGroup(groupFullPathName);
386         Principal rolePrincipal = new RolePrincipalImpl(roleFullPathName);
387         if (rolePrincipals.contains(rolePrincipal))
388         {
389             isGroupInRole = true;
390         }
391 
392         return isGroupInRole;
393     }
394 
395     /***
396      * @see org.apache.jetspeed.security.RoleManager#getRoles(java.lang.String)
397      */
398     public Iterator getRoles(String filter) throws SecurityException
399     {
400         List roles = new LinkedList();
401         Iterator rolePrincipals = roleSecurityHandler.getRolePrincipals(filter).iterator();
402         while (rolePrincipals.hasNext())
403         {
404             String roleName = ((Principal) rolePrincipals.next()).getName();
405             Role role = getRole(roleName);
406             roles.add(role);
407         }
408         return roles.iterator();
409     }
410 
411     /*** 
412      * @see org.apache.jetspeed.security.RoleManager#setRoleEnabled(java.lang.String, boolean)
413      */
414     public void setRoleEnabled(String roleFullPathName, boolean enabled) throws SecurityException
415     {
416         ArgUtil.notNull(new Object[] { roleFullPathName }, new String[] { "roleFullPathName" },
417         "setRoleEnabled(java.lang.String,boolean)");
418 
419         RolePrincipalImpl rolePrincipal = (RolePrincipalImpl)roleSecurityHandler.getRolePrincipal(roleFullPathName);
420         if (null == rolePrincipal)
421         {
422             throw new SecurityException(SecurityException.ROLE_DOES_NOT_EXIST.create(roleFullPathName));
423         }
424         if ( enabled != rolePrincipal.isEnabled() )
425         {
426             rolePrincipal.setEnabled(enabled);
427             roleSecurityHandler.setRolePrincipal(rolePrincipal);
428         }
429     }
430 }