]> source.dussan.org Git - archiva.git/commitdiff
[MRM-1736] map roles to ldap groups
authorOlivier Lamy <olamy@apache.org>
Tue, 8 Jan 2013 22:46:30 +0000 (22:46 +0000)
committerOlivier Lamy <olamy@apache.org>
Tue, 8 Jan 2013 22:46:30 +0000 (22:46 +0000)
git-svn-id: https://svn.apache.org/repos/asf/archiva/redback/redback-core/trunk@1430601 13f79535-47bb-0310-9956-ffa450edef68

12 files changed:
redback-authentication/redback-authentication-providers/redback-authentication-ldap/src/test/resources/security.properties
redback-authorization/redback-authorization-providers/redback-authorization-ldap/pom.xml
redback-authorization/redback-authorization-providers/redback-authorization-ldap/src/main/java/org/apache/archiva/redback/authorization/ldap/LdapAuthorizer.java
redback-common/redback-common-ldap/src/main/java/org/apache/archiva/redback/common/ldap/role/DefaultLdapRoleMapper.java
redback-common/redback-common-ldap/src/main/java/org/apache/archiva/redback/common/ldap/role/LdapRoleMapper.java
redback-common/redback-common-test-resources/src/main/resources/org/apache/archiva/redback/config-defaults.properties
redback-configuration/src/main/java/org/apache/archiva/redback/configuration/UserConfigurationKeys.java
redback-configuration/src/main/resources/org/apache/archiva/redback/config-defaults.properties
redback-data-management/src/test/resources/org/apache/archiva/redback/config-defaults.properties
redback-integrations/redback-common-integrations/src/main/java/org/apache/archiva/redback/integration/checks/security/GuestUserEnvironmentCheck.java
redback-integrations/redback-rest/redback-rest-services/src/main/java/org/apache/archiva/redback/rest/services/DefaultUserService.java
redback-rbac/redback-rbac-model/src/main/java/org/apache/archiva/redback/rbac/AbstractRBACManager.java

index ad56691fa22c121587f3f9b93eb7175f2232fc58..747e94c1c62aa9ad34a96a2d8489ae1a162166e2 100644 (file)
       <groupId>org.apache.archiva.redback</groupId>
       <artifactId>redback-authorization-api</artifactId>
     </dependency>
+    <dependency>
+      <groupId>org.apache.archiva.redback</groupId>
+      <artifactId>redback-rbac-model</artifactId>
+    </dependency>
     <dependency>
       <groupId>org.springframework</groupId>
       <artifactId>spring-context-support</artifactId>
             </Export-Package>
             <Import-Package>
               org.apache.archiva.redback.authorization;version=${project.version},
-              org.springframework.stereotype;version="[3,4)"
+              org.springframework.stereotype;version="[3,4)",
+              javax.inject,
+              org.apache.archiva.redback.common.ldap,
+              org.apache.archiva.redback.common.ldap.role,
+              org.apache.archiva.redback.rbac,
+              org.apache.commons.lang,
+              org.slf4j
             </Import-Package>
           </instructions>
         </configuration>
index f7191a853afa929d918aee7b2c290f0f59944388..22ecb576563155185be4a67c39f2dc3bf0b31745 100644 (file)
@@ -22,8 +22,33 @@ import org.apache.archiva.redback.authorization.AuthorizationDataSource;
 import org.apache.archiva.redback.authorization.AuthorizationException;
 import org.apache.archiva.redback.authorization.AuthorizationResult;
 import org.apache.archiva.redback.authorization.Authorizer;
+import org.apache.archiva.redback.common.ldap.MappingException;
+import org.apache.archiva.redback.common.ldap.role.LdapRoleMapper;
+import org.apache.archiva.redback.rbac.Permission;
+import org.apache.archiva.redback.rbac.RBACManager;
+import org.apache.archiva.redback.rbac.RbacManagerException;
+import org.apache.archiva.redback.rbac.RbacObjectNotFoundException;
+import org.apache.archiva.redback.rbac.Resource;
+import org.apache.archiva.redback.rbac.Role;
+import org.apache.archiva.redback.rbac.UserAssignment;
+import org.apache.archiva.redback.users.UserManagerException;
+import org.apache.archiva.redback.users.UserNotFoundException;
+import org.apache.commons.lang.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.springframework.stereotype.Service;
 
+import javax.inject.Inject;
+import javax.inject.Named;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
 /**
  * @author Olivier Lamy
  * @since 2.1
@@ -32,6 +57,17 @@ import org.springframework.stereotype.Service;
 public class LdapAuthorizer
     implements Authorizer
 {
+
+    private Logger log = LoggerFactory.getLogger( getClass() );
+
+    @Inject
+    @Named( value = "rbacManager#cached" )
+    private RBACManager rbacManager;
+
+    @Inject
+    private LdapRoleMapper ldapRoleMapper;
+
+
     public String getId()
     {
         return "ldap";
@@ -40,7 +76,232 @@ public class LdapAuthorizer
     public AuthorizationResult isAuthorized( AuthorizationDataSource source )
         throws AuthorizationException
     {
+
+        String userName = StringUtils.isEmpty( source.getPrincipal() ) ? "guest" : source.getPrincipal();
+        String operation = source.getPermission();
+        String resource = source.getResource();
+        try
+        {
+            List<String> ldapGroups = ldapRoleMapper.getGroups( userName );
+
+            List<String> roles = mapLdapGroups( ldapGroups );
+
+            Map<String, List<Permission>> permissionMap = getAssignedPermissionMap( roles );
+
+            if ( permissionMap.keySet().contains( operation ) )
+            {
+                for ( Permission permission : permissionMap.get( operation ) )
+                {
+
+                    log.debug( "checking permission {} for operation {} resource {}",
+                               ( permission != null ? permission.getName() : "null" ), operation, resource );
+
+                    if ( evaluate( permission, operation, resource, userName ) )
+                    {
+                        return new AuthorizationResult( true, permission, null );
+                    }
+                }
+
+                log.debug( "no permission found for operation {} resource {}", operation, resource );
+            }
+            else
+            {
+                log.debug( "permission map does not contain operation: {}", operation );
+            }
+
+        }
+        catch ( MappingException e )
+        {
+            log.info( "skip MappingException trying to find LDAP roles for user: '{}", userName );
+        }
+        catch ( RbacManagerException e )
+        {
+            log.info( "skip RbacManagerException trying to find LDAP roles for user: '{}", userName );
+        }
         return null;
+
+    }
+
+    protected List<String> mapLdapGroups( List<String> groups )
+        throws MappingException
+    {
+        List<String> roles = new ArrayList<String>();
+
+        Map<String, String> mapping = ldapRoleMapper.getLdapGroupMappings();
+
+        for ( String group : groups )
+        {
+            String role = mapping.get( group );
+            if ( role != null )
+            {
+                roles.add( role );
+            }
+        }
+
+        return roles;
+    }
+
+    public Map<String, List<Permission>> getAssignedPermissionMap( List<String> roles )
+        throws RbacObjectNotFoundException, RbacManagerException
+    {
+        return getPermissionMapByOperation( getAssignedPermissions( roles ) );
+    }
+
+    public Set<Permission> getAssignedPermissions( List<String> roles )
+        throws RbacObjectNotFoundException, RbacManagerException
+    {
+
+        Set<Permission> permissionSet = new HashSet<Permission>();
+
+        boolean childRoleNamesUpdated = false;
+
+        Iterator<String> it = roles.iterator();
+        while ( it.hasNext() )
+        {
+            String roleName = it.next();
+            try
+            {
+                Role role = rbacManager.getRole( roleName );
+                gatherUniquePermissions( role, permissionSet );
+            }
+            catch ( RbacObjectNotFoundException e )
+            {
+                // Found a bad role name. remove it!
+                it.remove();
+                childRoleNamesUpdated = true;
+            }
+        }
+
+        return permissionSet;
+    }
+
+    private void gatherUniquePermissions( Role role, Collection<Permission> coll )
+        throws RbacManagerException
+    {
+        if ( role.getPermissions() != null )
+        {
+            for ( Permission permission : role.getPermissions() )
+            {
+                if ( !coll.contains( permission ) )
+                {
+                    coll.add( permission );
+                }
+            }
+        }
+
+        if ( role.hasChildRoles() )
+        {
+            Map<String, Role> childRoles = getChildRoles( role );
+            Iterator<Role> it = childRoles.values().iterator();
+            while ( it.hasNext() )
+            {
+                Role child = it.next();
+                gatherUniquePermissions( child, coll );
+            }
+        }
+    }
+
+    public Map<String, Role> getChildRoles( Role role )
+        throws RbacManagerException
+    {
+        Map<String, Role> childRoles = new HashMap<String, Role>();
+
+        boolean childRoleNamesUpdated = false;
+
+        Iterator<String> it = role.getChildRoleNames().listIterator();
+        while ( it.hasNext() )
+        {
+            String roleName = it.next();
+            try
+            {
+                Role child = rbacManager.getRole( roleName );
+                childRoles.put( child.getName(), child );
+            }
+            catch ( RbacObjectNotFoundException e )
+            {
+                // Found a bad roleName! - remove it.
+                it.remove();
+                childRoleNamesUpdated = true;
+            }
+        }
+
+        return childRoles;
+    }
+
+
+    private Map<String, List<Permission>> getPermissionMapByOperation( Collection<Permission> permissions )
+    {
+        Map<String, List<Permission>> userPermMap = new HashMap<String, List<Permission>>();
+
+        for ( Permission permission : permissions )
+        {
+            List<Permission> permList = userPermMap.get( permission.getOperation().getName() );
+
+            if ( permList != null )
+            {
+                permList.add( permission );
+            }
+            else
+            {
+                List<Permission> newPermList = new ArrayList<Permission>( permissions.size() );
+                newPermList.add( permission );
+                userPermMap.put( permission.getOperation().getName(), newPermList );
+            }
+        }
+
+        return userPermMap;
+    }
+
+    public boolean evaluate( Permission permission, String operation, String resource, String principal )
+    {
+        String permissionResource = permission.getResource().getIdentifier();
+
+        // expression evaluation checking
+        /*if ( permissionResource.startsWith( "${" ) )
+        {
+            String tempStr = permissionResource.substring( 2, permissionResource.indexOf( '}' ) );
+
+            if ( "username".equals( tempStr ) )
+            {
+                try
+                {
+                    permissionResource = userManager.findUser( principal ).getUsername();
+                }
+                catch ( UserNotFoundException e )
+                {
+                    throw new PermissionEvaluationException( "unable to locate user to retrieve username", e );
+                }
+                catch ( UserManagerException e )
+                {
+                    throw new PermissionEvaluationException( "trouble finding user: " + e.getMessage(), e );
+                }
+            }
+        }*/
+
+        // check if this permission applies to the operation at all
+        if ( permission.getOperation().getName().equals( operation ) )
+        {
+            // check if it is a global resource, if it is then since the operations match we return true
+            if ( Resource.GLOBAL.equals( permission.getResource().getIdentifier() ) )
+            {
+                return true;
+            }
+
+            // if we are not checking a specific resource, the operation is enough
+            if ( resource == null )
+            {
+                return true;
+            }
+
+            // check if the resource identifier of the permission matches the resource we are checking against
+            // if it does then return true
+            if ( permissionResource.equals( resource ) )
+            {
+                return true;
+            }
+        }
+
+        return false;
     }
 
     public boolean isFinalImplementation()
index 721ea61e8c333abe59e573a9454c4afdaeab9139..82e97881436d093908c9bd51fe66a77387efec28 100644 (file)
@@ -40,6 +40,7 @@ import javax.naming.directory.SearchControls;
 import javax.naming.directory.SearchResult;
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
@@ -76,9 +77,9 @@ public class DefaultLdapRoleMapper
     {
         this.ldapGroupClass = userConf.getString( UserConfigurationKeys.LDAP_GROUPS_CLASS, this.ldapGroupClass );
 
-        this.groupsDn = userConf.getString( UserConfigurationKeys.LDAP_GROUPS_BASEDN, this.groupsDn );
+        this.groupsDn = userConf.getConcatenatedList( UserConfigurationKeys.LDAP_GROUPS_BASEDN, this.groupsDn );
 
-        this.baseDn = userConf.getString( UserConfigurationKeys.LDAP_BASEDN, this.baseDn );
+        this.baseDn = userConf.getConcatenatedList( UserConfigurationKeys.LDAP_BASEDN, this.baseDn );
     }
 
     public String getLdapGroup( String role )
@@ -345,8 +346,11 @@ public class DefaultLdapRoleMapper
 
     public Map<String, String> getLdapGroupMappings()
     {
-        log.warn( "getLdapGroupMappings not implemented" );
-        return Collections.emptyMap();
+        Map<String, String> map = new HashMap<String, String>();
+        map.put( "archiva-admin", "System Administrator" );
+        //log.warn( "getLdapGroupMappings not implemented" );
+        //return Collections.emptyMap();
+        return map;
     }
 
     //---------------------------------
index e37cfa34eb2c928a51b222e263a6fb2010aabf79..3ba48c07bc8466abb0730baf8b308ddbf018809b 100644 (file)
@@ -88,7 +88,7 @@ public interface LdapRoleMapper
         throws MappingException;
 
     /**
-     * @return Map of corresponding Redback role (key) and LDAP group (value)
+     * @return Map of corresponding LDAP group (key) and Redback role (value)
      */
     Map<String, String> getLdapGroupMappings()
         throws MappingException;
index 31b0bb2a91eaf220e6743c9638a68e9813af5aa9..4290cb4cf05b6b63e5f332c460a863ec34ee1328 100644 (file)
@@ -78,6 +78,7 @@ security.signon.timeout=30
 # --------------------------------------------------------------------
 # Default Username Values
 redback.default.admin=admin
+redback.default.guest=guest
 
 # --------------------------------------------------------------------
 # Security Policies
index b6d401d966b72835e2e24738d4eef87eafe410ae..cde2c962e76518dc1604414778ea72553b907b36 100644 (file)
@@ -28,6 +28,8 @@ public interface UserConfigurationKeys
 
     String DEFAULT_ADMIN = "redback.default.admin";
 
+    String DEFAULT_GUEST = "redback.default.guest";
+
     String EMAIL_FROM_ADDRESS = "email.from.address";
 
     String EMAIL_FROM_NAME = "email.from.name";
index 26b6e8d822f6bffc5746fd66c4ad6c90b67208b5..402aaf97ade3b6784062b204d9dc3a1fe1a27045 100644 (file)
@@ -83,6 +83,7 @@ security.signon.timeout=30
 # --------------------------------------------------------------------
 # Default Username Values
 redback.default.admin=admin
+redback.default.guest=guest
 
 # --------------------------------------------------------------------
 # Security Policies
index eeecfea0e9e9aa533baf8cde2d399be7b73744e5..f749aae8fe97def41b8223c79d84bec11ad851d4 100644 (file)
@@ -82,6 +82,7 @@ security.signon.timeout=30
 # --------------------------------------------------------------------
 # Default Username Values
 redback.default.admin=admin
+redback.default.guest=guest
 
 # --------------------------------------------------------------------
 # Security Policies
index 17d891ab811502b81f0ce39914a069e4b06b9d1b..fcbcb94f1cbd5e11c8223347f2c2efeada2687f1 100644 (file)
@@ -19,6 +19,8 @@ package org.apache.archiva.redback.integration.checks.security;
  * under the License.
  */
 
+import org.apache.archiva.redback.configuration.UserConfiguration;
+import org.apache.archiva.redback.configuration.UserConfigurationKeys;
 import org.apache.archiva.redback.policy.UserSecurityPolicy;
 import org.apache.archiva.redback.role.RoleManagerException;
 import org.apache.archiva.redback.users.User;
@@ -31,6 +33,7 @@ import org.apache.archiva.redback.users.UserManager;
 import org.springframework.stereotype.Service;
 
 import javax.inject.Inject;
+import javax.inject.Named;
 import java.util.List;
 
 /**
@@ -49,6 +52,10 @@ public class GuestUserEnvironmentCheck
     @Inject
     private SecuritySystem securitySystem;
 
+    @Inject
+    @Named( value = "userConfiguration#default" )
+    private UserConfiguration config;
+
     /**
      * boolean detailing if this environment check has been executed
      */
@@ -86,7 +93,7 @@ public class GuestUserEnvironmentCheck
 
             try
             {
-                roleManager.assignRole( "guest", guest.getUsername() );
+                roleManager.assignRole( config.getString( UserConfigurationKeys.DEFAULT_GUEST ), guest.getUsername() );
             }
             catch ( RoleManagerException rpe )
             {
index 9093839126bae2dac9443b604330f01425fd7eb4..eb9f06e2ecdf7ec94165ba44622c469c5e8e8a73 100644 (file)
@@ -453,7 +453,7 @@ public class DefaultUserService
             org.apache.archiva.redback.users.User user = userManager.createGuestUser();
             user.setPasswordChangeRequired( false );
             user = userManager.updateUser( user, false );
-            roleManager.assignRole( "guest", user.getUsername() );
+            roleManager.assignRole( config.getString( UserConfigurationKeys.DEFAULT_GUEST ), user.getUsername() );
             return getSimpleUser( user );
         }
         catch ( RoleManagerException e )
index 6dec253e77876e13aef5c83ec8dc08e308d8b896..a7fd7ac5d879bb4692130e143884a84ada374fea 100644 (file)
@@ -723,7 +723,7 @@ public abstract class AbstractRBACManager
         Iterator<String> it = role.getChildRoleNames().listIterator();
         while ( it.hasNext() )
         {
-            String roleName = (String) it.next();
+            String roleName = it.next();
             try
             {
                 Role child = getRole( roleName );