diff --git a/archiva-web/archiva-security/pom.xml b/archiva-web/archiva-security/pom.xml index 5837eee9f..5ba0428be 100644 --- a/archiva-web/archiva-security/pom.xml +++ b/archiva-web/archiva-security/pom.xml @@ -28,24 +28,42 @@ archiva-security Archiva Web :: Security Configuration + + org.apache.maven.archiva + archiva-configuration + + + org.codehaus.plexus.redback + redback-system + + + org.codehaus.plexus.redback + redback-rbac-model + org.codehaus.plexus.redback redback-rbac-role-manager + + + org.codehaus.plexus.redback + redback-authorization-rbac + test + + + org.codehaus.plexus.redback + redback-keys-memory + test + + + org.codehaus.plexus.redback + redback-users-memory + test + org.codehaus.plexus.redback redback-rbac-memory test - - org.codehaus.plexus.redback - redback-xwork-integration - test - - - org.apache.derby - derby - test - diff --git a/archiva-web/archiva-security/src/main/java/org/apache/maven/archiva/security/AccessDeniedException.java b/archiva-web/archiva-security/src/main/java/org/apache/maven/archiva/security/AccessDeniedException.java new file mode 100644 index 000000000..2c3ea5e40 --- /dev/null +++ b/archiva-web/archiva-security/src/main/java/org/apache/maven/archiva/security/AccessDeniedException.java @@ -0,0 +1,40 @@ +package org.apache.maven.archiva.security; + +/* + * 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. + */ + +/** + * AccessDeniedException + * + * @author Joakim Erdfelt + * @version $Id$ + */ +public class AccessDeniedException + extends ArchivaSecurityException +{ + public AccessDeniedException( String message, Throwable cause ) + { + super( message, cause ); + } + + public AccessDeniedException( String message ) + { + super( message ); + } +} diff --git a/archiva-web/archiva-security/src/main/java/org/apache/maven/archiva/security/ArchivaRoleConstants.java b/archiva-web/archiva-security/src/main/java/org/apache/maven/archiva/security/ArchivaRoleConstants.java index 0be90a7b0..e2d97acc0 100644 --- a/archiva-web/archiva-security/src/main/java/org/apache/maven/archiva/security/ArchivaRoleConstants.java +++ b/archiva-web/archiva-security/src/main/java/org/apache/maven/archiva/security/ArchivaRoleConstants.java @@ -68,4 +68,18 @@ public class ArchivaRoleConstants public static final String TEMPLATE_REPOSITORY_MANAGER = "archiva-repository-manager"; public static final String TEMPLATE_REPOSITORY_OBSERVER = "archiva-repository-observer"; + + public static final String TEMPLATE_SYSTEM_ADMIN = "archiva-system-administrator"; + + public static final String TEMPLATE_GUEST = "archiva-guest"; + + public static String toRepositoryObserverRoleId( String repoId ) + { + return TEMPLATE_REPOSITORY_OBSERVER + "-" + repoId; + } + + public static String toRepositoryObserverRoleName( String repoId ) + { + return REPOSITORY_OBSERVER_ROLE_PREFIX + " - " + repoId; + } } diff --git a/archiva-web/archiva-security/src/main/java/org/apache/maven/archiva/security/ArchivaSecurityException.java b/archiva-web/archiva-security/src/main/java/org/apache/maven/archiva/security/ArchivaSecurityException.java new file mode 100644 index 000000000..47973fc25 --- /dev/null +++ b/archiva-web/archiva-security/src/main/java/org/apache/maven/archiva/security/ArchivaSecurityException.java @@ -0,0 +1,42 @@ +package org.apache.maven.archiva.security; + +/* + * 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. + */ + +import org.apache.maven.archiva.common.ArchivaException; + +/** + * ArchivaSecurityException + * + * @author Joakim Erdfelt + * @version $Id$ + */ +public class ArchivaSecurityException + extends ArchivaException +{ + public ArchivaSecurityException( String message, Throwable cause ) + { + super( message, cause ); + } + + public ArchivaSecurityException( String message ) + { + super( message ); + } +} diff --git a/archiva-web/archiva-security/src/main/java/org/apache/maven/archiva/security/ArchivaStandardRolesCheck.java b/archiva-web/archiva-security/src/main/java/org/apache/maven/archiva/security/ArchivaStandardRolesCheck.java new file mode 100644 index 000000000..434c2f612 --- /dev/null +++ b/archiva-web/archiva-security/src/main/java/org/apache/maven/archiva/security/ArchivaStandardRolesCheck.java @@ -0,0 +1,103 @@ +package org.apache.maven.archiva.security; + +/* + * 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. + */ + +import org.codehaus.plexus.logging.AbstractLogEnabled; +import org.codehaus.plexus.redback.rbac.RBACManager; +import org.codehaus.plexus.redback.system.check.EnvironmentCheck; + +import java.util.List; + +/** + * ArchivaStandardRolesCheck tests for the existance of expected / standard roles and permissions. + * + * @author Joakim Erdfelt + * @version $Id$ + * + * @plexus.component role="org.codehaus.plexus.redback.system.check.EnvironmentCheck" + * role-hint="required-roles" + */ +public class ArchivaStandardRolesCheck + extends AbstractLogEnabled + implements EnvironmentCheck +{ + /** + * @plexus.requirement role-hint="cached" + */ + private RBACManager rbacManager; + + /** + * boolean detailing if this environment check has been executed + */ + private boolean checked = false; + + @SuppressWarnings("unchecked") + public void validateEnvironment( List violations ) + { + if ( !checked ) + { + String expectedRoles[] = new String[] { + ArchivaRoleConstants.SYSTEM_ADMINISTRATOR_ROLE, + ArchivaRoleConstants.GLOBAL_REPOSITORY_MANAGER_ROLE, + ArchivaRoleConstants.GLOBAL_REPOSITORY_OBSERVER_ROLE, + ArchivaRoleConstants.GUEST_ROLE, + ArchivaRoleConstants.REGISTERED_USER_ROLE, + ArchivaRoleConstants.USER_ADMINISTRATOR_ROLE }; + + getLogger().info( "Checking the existance of required roles." ); + + for ( String roleName : expectedRoles ) + { + if ( !rbacManager.roleExists( roleName ) ) + { + violations.add( "Unable to validate the existances of the '" + roleName + "' role." ); + } + } + + String expectedOperations[] = new String[] { + ArchivaRoleConstants.OPERATION_MANAGE_USERS, + ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION, + ArchivaRoleConstants.OPERATION_REGENERATE_INDEX, + ArchivaRoleConstants.OPERATION_RUN_INDEXER, + ArchivaRoleConstants.OPERATION_ACCESS_REPORT, + ArchivaRoleConstants.OPERATION_ADD_REPOSITORY, + ArchivaRoleConstants.OPERATION_DELETE_REPOSITORY, + ArchivaRoleConstants.OPERATION_REPOSITORY_ACCESS, + ArchivaRoleConstants.OPERATION_EDIT_REPOSITORY, + ArchivaRoleConstants.OPERATION_REPOSITORY_UPLOAD, + ArchivaRoleConstants.OPERATION_REPOSITORY_ACCESS, + "archiva-guest" }; + + getLogger().info( "Checking the existance of required operations." ); + + for ( String operation : expectedOperations ) + { + if ( !rbacManager.operationExists( operation ) ) + { + violations.add( "Unable to validate the existances of the '" + operation + "' operation." ); + } + } + + checked = true; + } + + } + +} diff --git a/archiva-web/archiva-security/src/main/java/org/apache/maven/archiva/security/DefaultUserRepositories.java b/archiva-web/archiva-security/src/main/java/org/apache/maven/archiva/security/DefaultUserRepositories.java new file mode 100644 index 000000000..edac526d4 --- /dev/null +++ b/archiva-web/archiva-security/src/main/java/org/apache/maven/archiva/security/DefaultUserRepositories.java @@ -0,0 +1,132 @@ +package org.apache.maven.archiva.security; + +/* + * 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. + */ + +import org.codehaus.plexus.redback.rbac.Permission; +import org.codehaus.plexus.redback.rbac.RBACManager; +import org.codehaus.plexus.redback.rbac.RbacManagerException; +import org.codehaus.plexus.redback.rbac.RbacObjectNotFoundException; +import org.codehaus.plexus.redback.role.RoleManager; +import org.codehaus.plexus.redback.role.RoleManagerException; +import org.codehaus.plexus.redback.system.SecuritySystem; +import org.codehaus.plexus.redback.users.User; +import org.codehaus.plexus.redback.users.UserNotFoundException; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +/** + * DefaultUserRepositories + * + * @author Joakim Erdfelt + * @version $Id$ + * + * @plexus.component role="org.apache.maven.archiva.security.UserRepositories" + * role-hint="default" + */ +public class DefaultUserRepositories + implements UserRepositories +{ + /** + * @plexus.requirement + */ + private SecuritySystem securitySystem; + + /** + * @plexus.requirement role-hint="cached" + */ + private RBACManager rbacManager; + + /** + * @plexus.requirement role-hint="default" + */ + private RoleManager roleManager; + + public List getObservableRepositoryIds( String principal ) + throws PrincipalNotFoundException, AccessDeniedException, ArchivaSecurityException + { + + try + { + User user = securitySystem.getUserManager().findUser( principal ); + + if ( user.isLocked() ) + { + throw new AccessDeniedException( "User " + principal + "(" + user.getFullName() + ") is locked." ); + } + + Map> permissionMap = rbacManager.getAssignedPermissionMap( principal ); + + List repoIds = new ArrayList(); + + for( Entry> entry: permissionMap.entrySet() ) + { + List perms = entry.getValue(); + + for( Permission perm: perms ) + { + System.out.println( "Principal[" + principal + "] : Permission[" + entry.getKey() + "]:" + perm.getName() + " - Operation:" + + perm.getOperation().getName() + " - Resource:" + perm.getResource().getIdentifier() ); + } + } + + System.out.println("-"); + + return repoIds; + } + catch ( UserNotFoundException e ) + { + throw new PrincipalNotFoundException( "Unable to find principal " + principal + "" ); + } + catch ( RbacObjectNotFoundException e ) + { + throw new PrincipalNotFoundException( "Unable to find user role assignments for user " + principal, e ); + } + catch ( RbacManagerException e ) + { + throw new ArchivaSecurityException( "Unable to initialize underlying security framework: " + e.getMessage(), + e ); + } + } + + public void createMissingRepositoryRoles( String repoId ) + throws ArchivaSecurityException + { + try + { + if ( !roleManager.templatedRoleExists( ArchivaRoleConstants.TEMPLATE_REPOSITORY_OBSERVER, repoId ) ) + { + roleManager.createTemplatedRole( ArchivaRoleConstants.TEMPLATE_REPOSITORY_OBSERVER, repoId ); + } + + if ( !roleManager.templatedRoleExists( ArchivaRoleConstants.TEMPLATE_REPOSITORY_MANAGER, repoId ) ) + { + roleManager.createTemplatedRole( ArchivaRoleConstants.TEMPLATE_REPOSITORY_MANAGER, repoId ); + } + } + catch ( RoleManagerException e ) + { + throw new ArchivaSecurityException( "Unable to create roles for configured repositories: " + e.getMessage(), + e ); + } + } +} diff --git a/archiva-web/archiva-security/src/main/java/org/apache/maven/archiva/security/PrincipalNotFoundException.java b/archiva-web/archiva-security/src/main/java/org/apache/maven/archiva/security/PrincipalNotFoundException.java new file mode 100644 index 000000000..196204436 --- /dev/null +++ b/archiva-web/archiva-security/src/main/java/org/apache/maven/archiva/security/PrincipalNotFoundException.java @@ -0,0 +1,40 @@ +package org.apache.maven.archiva.security; + +/* + * 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. + */ + +/** + * PrincipalNotFoundException + * + * @author Joakim Erdfelt + * @version $Id$ + */ +public class PrincipalNotFoundException + extends ArchivaSecurityException +{ + public PrincipalNotFoundException( String message, Throwable cause ) + { + super( message, cause ); + } + + public PrincipalNotFoundException( String message ) + { + super( message ); + } +} diff --git a/archiva-web/archiva-security/src/main/java/org/apache/maven/archiva/security/SecurityStartup.java b/archiva-web/archiva-security/src/main/java/org/apache/maven/archiva/security/SecurityStartup.java new file mode 100644 index 000000000..8a6c51c96 --- /dev/null +++ b/archiva-web/archiva-security/src/main/java/org/apache/maven/archiva/security/SecurityStartup.java @@ -0,0 +1,206 @@ +package org.apache.maven.archiva.security; + +/* + * 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. + */ + +import org.apache.commons.collections.CollectionUtils; +import org.apache.maven.archiva.common.ArchivaException; +import org.apache.maven.archiva.configuration.ArchivaConfiguration; +import org.apache.maven.archiva.configuration.ConfigurationNames; +import org.apache.maven.archiva.configuration.ManagedRepositoryConfiguration; +import org.codehaus.plexus.logging.AbstractLogEnabled; +import org.codehaus.plexus.redback.rbac.RBACManager; +import org.codehaus.plexus.redback.rbac.RbacManagerException; +import org.codehaus.plexus.redback.rbac.UserAssignment; +import org.codehaus.plexus.redback.system.check.EnvironmentCheck; +import org.codehaus.plexus.registry.Registry; +import org.codehaus.plexus.registry.RegistryListener; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +/** + * SecurityStartup + * + * @author Joakim Erdfelt + * @version $Id$ + * + * @plexus.component role="org.apache.maven.archiva.security.SecurityStartup" + */ +public class SecurityStartup + extends AbstractLogEnabled + implements RegistryListener +{ + /** + * @plexus.requirement + */ + private UserRepositories userRepos; + + /** + * @plexus.requirement role-hint="cached" + */ + private RBACManager rbacManager; + + /** + * @plexus.requirement role="org.codehaus.plexus.redback.system.check.EnvironmentCheck" + */ + private Map checkers; + + /** + * @plexus.requirement + */ + private ArchivaConfiguration archivaConfiguration; + + public void afterConfigurationChange( Registry registry, String propertyName, Object propertyValue ) + { + if ( ConfigurationNames.isManagedRepositories( propertyName ) ) + { + createMissingManagedRepositoryRoles( archivaConfiguration.getConfiguration().getManagedRepositories() ); + } + } + + public void assignRepositoryObserverToGuestUser( List repos ) + { + for ( ManagedRepositoryConfiguration repoConfig : repos ) + { + String repoId = repoConfig.getId(); + + // TODO: Use the Redback / UserConfiguration..getString( "redback.default.guest" ) to get the right name. + String principal = "guest"; + + try + { + UserAssignment ua; + + if ( rbacManager.userAssignmentExists( principal ) ) + { + ua = rbacManager.getUserAssignment( principal ); + } + else + { + ua = rbacManager.createUserAssignment( principal ); + } + + ua.addRoleName( ArchivaRoleConstants.toRepositoryObserverRoleName( repoId ) ); + rbacManager.saveUserAssignment( ua ); + } + catch ( RbacManagerException e ) + { + getLogger().warn( + "Unable to add role [" + ArchivaRoleConstants.toRepositoryObserverRoleName( repoId ) + + "] to " + principal + " user.", e ); + } + } + } + + public void beforeConfigurationChange( Registry registry, String propertyName, Object propertyValue ) + { + /* do nothing */ + } + + public void createMissingManagedRepositoryRoles( List repos ) + { + // NOTE: Remote Repositories do not have roles or security placed around them. + + for ( ManagedRepositoryConfiguration repoConfig : repos ) + { + // manage roles for repositories + try + { + userRepos.createMissingRepositoryRoles( repoConfig.getId() ); + } + catch ( ArchivaSecurityException e ) + { + getLogger().warn( e.getMessage(), e ); + } + } + } + + public void createMissingRepositoryRoles( List repoIds ) + { + for ( String repoId : repoIds ) + { + // manage roles for repositories + try + { + userRepos.createMissingRepositoryRoles( repoId ); + } + catch ( ArchivaSecurityException e ) + { + getLogger().warn( e.getMessage(), e ); + } + } + } + + public void executeEnvironmentChecks() + throws ArchivaException + { + if ( ( checkers == null ) || CollectionUtils.isEmpty( checkers.values() ) ) + { + throw new ArchivaException( "Unable to initialize the Redback Security Environment, " + + "no Environment Check components found." ); + } + + List violations = new ArrayList(); + + for ( Entry entry : checkers.entrySet() ) + { + EnvironmentCheck check = entry.getValue(); + getLogger().info( "Running Environment Check: " + entry.getKey() ); + check.validateEnvironment( violations ); + } + + if ( CollectionUtils.isNotEmpty( violations ) ) + { + StringBuffer msg = new StringBuffer(); + msg.append( "EnvironmentCheck Failure.\n" ); + msg.append( "======================================================================\n" ); + msg.append( " ENVIRONMENT FAILURE !! \n" ); + msg.append( "\n" ); + + for ( String violation : violations ) + { + msg.append( violation ).append( "\n" ); + } + + msg.append( "\n" ); + msg.append( "======================================================================" ); + getLogger().fatalError( msg.toString() ); + + throw new ArchivaException( "Unable to initialize Redback Security Environment, [" + violations.size() + + "] violation(s) encountered, See log for details." ); + } + } + + public void startup() + throws ArchivaException + { + executeEnvironmentChecks(); + + createMissingManagedRepositoryRoles( archivaConfiguration.getConfiguration().getManagedRepositories() ); + archivaConfiguration.addChangeListener( this ); + + if ( archivaConfiguration.isDefaulted() ) + { + assignRepositoryObserverToGuestUser( archivaConfiguration.getConfiguration().getManagedRepositories() ); + } + } +} diff --git a/archiva-web/archiva-security/src/main/java/org/apache/maven/archiva/security/UserRepositories.java b/archiva-web/archiva-security/src/main/java/org/apache/maven/archiva/security/UserRepositories.java new file mode 100644 index 000000000..c448a26b3 --- /dev/null +++ b/archiva-web/archiva-security/src/main/java/org/apache/maven/archiva/security/UserRepositories.java @@ -0,0 +1,52 @@ +package org.apache.maven.archiva.security; + +/* + * 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. + */ + +import java.util.List; + +/** + * UserRepositories + * + * @author Joakim Erdfelt + * @version $Id$ + */ +public interface UserRepositories +{ + /** + * Get the list of observable repository ids for the user specified. + * + * @param principal the principle to obtain the observable repository ids from. + * @return the list of observable repository ids. + * @throws PrincipalNotFoundException + * @throws AccessDeniedException + * @throws ArchivaSecurityException + */ + public List getObservableRepositoryIds( String principal ) + throws PrincipalNotFoundException, AccessDeniedException, ArchivaSecurityException; + + /** + * Create any missing repository roles for the provided repository id. + * + * @param repoId the repository id to work off of. + * @throws ArchivaSecurityException if there was a problem creating the repository roles. + */ + public void createMissingRepositoryRoles( String repoId ) + throws ArchivaSecurityException; +} diff --git a/archiva-web/archiva-security/src/test/java/org/apache/maven/archiva/security/DefaultUserRepositoriesTest.java b/archiva-web/archiva-security/src/test/java/org/apache/maven/archiva/security/DefaultUserRepositoriesTest.java new file mode 100644 index 000000000..bd37e5e2c --- /dev/null +++ b/archiva-web/archiva-security/src/test/java/org/apache/maven/archiva/security/DefaultUserRepositoriesTest.java @@ -0,0 +1,234 @@ +package org.apache.maven.archiva.security; + +/* + * 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. + */ + +import org.apache.commons.lang.StringUtils; +import org.codehaus.plexus.PlexusTestCase; +import org.codehaus.plexus.redback.rbac.Operation; +import org.codehaus.plexus.redback.rbac.Permission; +import org.codehaus.plexus.redback.rbac.RBACManager; +import org.codehaus.plexus.redback.rbac.Resource; +import org.codehaus.plexus.redback.rbac.Role; +import org.codehaus.plexus.redback.rbac.UserAssignment; +import org.codehaus.plexus.redback.role.RoleManager; +import org.codehaus.plexus.redback.role.RoleManagerException; +import org.codehaus.plexus.redback.system.SecuritySystem; +import org.codehaus.plexus.redback.users.User; +import org.codehaus.plexus.redback.users.UserManager; + +import java.util.List; + +/** + * DefaultUserRepositoriesTest + * + * @author Joakim Erdfelt + * @version $Id$ + */ +public class DefaultUserRepositoriesTest + extends PlexusTestCase +{ + private static final String PERMISSION_READ_REPOSITORY = "Archiva Read Repository"; + + private static final String USER_GUEST = "guest"; + + private static final String USER_ADMIN = "admin"; + + private static final String USER_ALPACA = "alpaca"; + + private SecuritySystem securitySystem; + + private RBACManager rbacManager; + + private RoleManager roleManager; + + public void testGetObservableRepositoryIds() + throws Exception + { + UserRepositories userRepos = (UserRepositories) lookup( UserRepositories.class, "default" ); + assertNotNull( userRepos ); + + // create some users. + createUser( USER_ALPACA, "Al 'Archiva' Paca" ); + + assertEquals( "Expected users", 3, securitySystem.getUserManager().getUsers().size() ); + + // some unassigned repo observer roles. + userRepos.createMissingRepositoryRoles( "central" ); + userRepos.createMissingRepositoryRoles( "coporate" ); + userRepos.createMissingRepositoryRoles( "internal" ); + userRepos.createMissingRepositoryRoles( "snapshots" ); + userRepos.createMissingRepositoryRoles( "secret" ); + + // some assigned repo observer roles. + assignRepositoryObserverRole( USER_ALPACA, "central" ); + assignRepositoryObserverRole( USER_ALPACA, "corporate" ); + assignRepositoryObserverRole( USER_GUEST, "corporate" ); + // the global repo observer role. + assignGlobalRepositoryObserverRole( USER_ADMIN ); + + assertRepoIds( new String[] { "central", "corporate" }, userRepos.getObservableRepositoryIds( USER_ALPACA ) ); + assertRepoIds( new String[] { "coporate" }, userRepos.getObservableRepositoryIds( USER_GUEST ) ); + assertRepoIds( new String[] { "central", "internal", "corporate", "snapshots", "secret" }, userRepos + .getObservableRepositoryIds( USER_ADMIN ) ); + } + + private void assertRepoIds( String[] expectedRepoIds, List observableRepositoryIds ) + { + assertNotNull( "Observable Repository Ids cannot be null.", observableRepositoryIds ); + + if ( expectedRepoIds.length != observableRepositoryIds.size() ) + { + fail( "Size of Observable Repository Ids wrong, expected <" + expectedRepoIds.length + "> but got <" + + observableRepositoryIds.size() + "> instead. \nExpected: [" + StringUtils.join( expectedRepoIds, "," ) + + "]\nActual: [" + StringUtils.join( observableRepositoryIds.iterator(), "," ) + "]" ); + } + } + + private void assignGlobalRepositoryObserverRole( String principal ) + throws Exception + { + Role role = createRepositoryObserverRole( ArchivaRoleConstants.GLOBAL_REPOSITORY_OBSERVER_ROLE, + PERMISSION_READ_REPOSITORY, Resource.GLOBAL ); + assignRole( principal, role ); + } + + private void assignRepositoryObserverRole( String principal, String repoId ) + throws Exception + { + // String roleId = ArchivaRoleConstants.toRepositoryObserverRoleId( repoId ); + String roleId = ArchivaRoleConstants.toRepositoryObserverRoleName( repoId ); + roleManager.assignRole( roleId, principal ); + +// Role role = createRepositoryObserverRole( roleName, PERMISSION_READ_REPOSITORY, repoId ); +// assertEquals( roleName, role.getName() ); +// assignRole( principal, role ); + } + + private void assignRole( String principal, Role role ) + throws Exception + { + UserAssignment ua; + + if ( rbacManager.userAssignmentExists( principal ) ) + { + ua = rbacManager.getUserAssignment( principal ); + } + else + { + ua = rbacManager.createUserAssignment( principal ); + } + + ua.addRoleName( role ); + + rbacManager.saveUserAssignment( ua ); + } + + private void createRepositoryObserverRole( String repoId ) + throws Exception + { + createRepositoryObserverRole( ArchivaRoleConstants.toRepositoryObserverRoleName( repoId ), + PERMISSION_READ_REPOSITORY + "-" + repoId, repoId ); + } + + private Role createRepositoryObserverRole( String roleName, String permissionName, String resourceId ) + throws Exception + { + if ( rbacManager.roleExists( roleName ) ) + { + return rbacManager.getRole( roleName ); + } + + Permission perm; + Operation operationRepoAccess; + Resource resource; + + // if ( rbacManager.resourceExists( resourceId ) ) + // { + // resource = rbacManager.getResource( resourceId ); + // } + // else + // { + // resource = rbacManager.createResource( resourceId ); + // } + resource = rbacManager.createResource( resourceId ); + + // if ( rbacManager.operationExists( ArchivaRoleConstants.OPERATION_REPOSITORY_ACCESS ) ) + // { + // operationRepoAccess = rbacManager.getOperation( ArchivaRoleConstants.OPERATION_REPOSITORY_ACCESS ); + // } + // else + // { + // operationRepoAccess = rbacManager.createOperation( ArchivaRoleConstants.OPERATION_REPOSITORY_ACCESS ); + // } + operationRepoAccess = rbacManager.createOperation( ArchivaRoleConstants.OPERATION_REPOSITORY_ACCESS ); + + // if ( rbacManager.permissionExists( permissionName ) ) + // { + // perm = rbacManager.getPermission( permissionName ); + // } + // else + // { + // perm = rbacManager.createPermission( permissionName ); + // } + perm = rbacManager.createPermission( permissionName ); + perm.setOperation( operationRepoAccess ); + perm.setResource( resource ); + + Role role = rbacManager.createRole( roleName ); + role.addPermission( perm ); + + rbacManager.saveOperation( operationRepoAccess ); + rbacManager.savePermission( perm ); + rbacManager.saveRole( role ); + + return role; + } + + private User createUser( String principal, String fullname ) + { + UserManager userManager = securitySystem.getUserManager(); + + User user = userManager.createUser( principal, fullname, principal + "@testable.archiva.apache.org" ); + securitySystem.getPolicy().setEnabled( false ); + userManager.addUser( user ); + securitySystem.getPolicy().setEnabled( true ); + + return user; + } + + @Override + protected void setUp() + throws Exception + { + super.setUp(); + + securitySystem = (SecuritySystem) lookup( SecuritySystem.class, "testable" ); + rbacManager = (RBACManager) lookup( RBACManager.class, "memory" ); + roleManager = (RoleManager) lookup( RoleManager.class, "default" ); + + // Setup Admin User. + User adminUser = createUser( USER_ADMIN, "Admin User" ); + roleManager.assignRole( ArchivaRoleConstants.TEMPLATE_SYSTEM_ADMIN, adminUser.getPrincipal().toString() ); + + // Setup Guest User. + User guestUser = createUser( USER_GUEST, "Guest User" ); + roleManager.assignRole( ArchivaRoleConstants.TEMPLATE_GUEST, guestUser.getPrincipal().toString() ); + } +} diff --git a/archiva-web/archiva-security/src/test/java/org/apache/maven/archiva/security/SecurityStartupTest.java b/archiva-web/archiva-security/src/test/java/org/apache/maven/archiva/security/SecurityStartupTest.java new file mode 100644 index 000000000..f3924f934 --- /dev/null +++ b/archiva-web/archiva-security/src/test/java/org/apache/maven/archiva/security/SecurityStartupTest.java @@ -0,0 +1,49 @@ +package org.apache.maven.archiva.security; + +/* + * 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. + */ + +import org.codehaus.plexus.PlexusTestCase; + +/** + * SecurityStartupTest + * + * @author Joakim Erdfelt + * @version $Id$ + */ +public class SecurityStartupTest + extends PlexusTestCase +{ + private SecurityStartup secStart; + + @Override + protected void setUp() + throws Exception + { + super.setUp(); + + secStart = (SecurityStartup) lookup( SecurityStartup.class ); + } + + public void testEnvironmentChecks() + throws Exception + { + secStart.executeEnvironmentChecks(); + } +} diff --git a/archiva-web/archiva-security/src/test/resources/META-INF/redback/redback-core.xml b/archiva-web/archiva-security/src/test/resources/META-INF/redback/redback-core.xml new file mode 100644 index 000000000..794d52762 --- /dev/null +++ b/archiva-web/archiva-security/src/test/resources/META-INF/redback/redback-core.xml @@ -0,0 +1,195 @@ + + + 1.0.0 + Redback XWork Integration Security Core + + + global + * + true + global resource implies full access for authorization + + + username + ${username} + true + replaced with the username of the principal at authorization check time + + + + + configuration-edit + configuration-edit + edit configuration + true + + + user-management-user-create + user-management-user-create + create user + true + + + user-management-user-edit + user-management-user-edit + edit user + true + + + user-management-user-role + user-management-user-role + user roles + true + + + user-management-user-delete + user-management-user-delete + delete user + true + + + user-management-user-list + user-management-user-list + list users + true + + + user-management-role-grant + user-management-role-grant + grant role + true + + + user-management-role-drop + user-management-role-drop + drop role + true + + + user-management-rbac-admin + user-management-rbac-admin + administer rbac + true + + + guest-access + guest-access + access guest + true + + + + + system-administrator + System Administrator + true + true + + + edit-redback-configuration + Edit Redback Configuration + configuration-edit + global + true + + + manage-rbac-setup + User RBAC Management + user-management-rbac-admin + global + true + + + + user-administrator + + + + user-administrator + User Administrator + true + true + + + drop-roles-for-anyone + Drop Roles for Anyone + user-management-role-drop + global + true + + + grant-roles-for-anyone + Grant Roles for Anyone + user-management-role-grant + global + true + + + user-create + Create Users + user-management-user-create + global + true + + + user-delete + Delete Users + user-management-user-delete + global + true + + + user-edit + Edit Users + user-management-user-edit + global + true + + + access-users-roles + Access Users Roles + user-management-user-role + global + true + + + access-user-list + Access User List + user-management-user-list + global + true + + + + + registered-user + Registered User + true + true + + + edit-user-by-username + Edit User Data by Username + user-management-user-edit + username + true + + + + + guest + Guest + true + true + + + guest-permission + Guest Permission + guest-access + global + true + + + + + \ No newline at end of file diff --git a/archiva-web/archiva-security/src/test/resources/org/apache/maven/archiva/security/DefaultUserRepositoriesTest.xml b/archiva-web/archiva-security/src/test/resources/org/apache/maven/archiva/security/DefaultUserRepositoriesTest.xml new file mode 100644 index 000000000..99c0b9013 --- /dev/null +++ b/archiva-web/archiva-security/src/test/resources/org/apache/maven/archiva/security/DefaultUserRepositoriesTest.xml @@ -0,0 +1,166 @@ + + + + + + org.apache.maven.archiva.security.UserRepositories + default + org.apache.maven.archiva.security.DefaultUserRepositories + DefaultUserRepositories + + + org.codehaus.plexus.redback.system.SecuritySystem + testable + securitySystem + + + org.codehaus.plexus.redback.rbac.RBACManager + memory + rbacManager + + + org.codehaus.plexus.redback.role.RoleManager + default + roleManager + + + + + + org.codehaus.plexus.redback.system.SecuritySystem + testable + org.codehaus.plexus.redback.system.DefaultSecuritySystem + DefaultSecuritySystem: + + + org.codehaus.plexus.redback.authentication.AuthenticationManager + authnManager + + + org.codehaus.plexus.redback.authorization.Authorizer + rbac + authorizer + + + org.codehaus.plexus.redback.users.UserManager + memory + userManager + + + org.codehaus.plexus.redback.keys.KeyManager + memory + keyManager + + + org.codehaus.plexus.redback.policy.UserSecurityPolicy + policy + + + + + + org.codehaus.plexus.redback.authorization.Authorizer + rbac + org.codehaus.plexus.redback.authorization.rbac.RbacAuthorizer + RbacAuthorizer: + + + org.codehaus.plexus.redback.rbac.RBACManager + memory + manager + + + org.codehaus.plexus.redback.users.UserManager + memory + userManager + + + org.codehaus.plexus.redback.authorization.rbac.evaluator.PermissionEvaluator + default + evaluator + + + org.codehaus.plexus.redback.configuration.UserConfiguration + default + config + + + + + + org.codehaus.plexus.redback.authorization.rbac.evaluator.PermissionEvaluator + default + org.codehaus.plexus.redback.authorization.rbac.evaluator.DefaultPermissionEvaluator + + + org.codehaus.plexus.redback.users.UserManager + memory + userManager + + + + + + org.codehaus.plexus.redback.role.RoleManager + default + org.codehaus.plexus.redback.role.DefaultRoleManager + RoleProfileManager: + + + org.codehaus.plexus.redback.role.merger.RoleModelMerger + default + modelMerger + + + org.codehaus.plexus.redback.role.validator.RoleModelValidator + default + modelValidator + + + org.codehaus.plexus.redback.role.processor.RoleModelProcessor + default + modelProcessor + + + org.codehaus.plexus.redback.role.template.RoleTemplateProcessor + default + templateProcessor + + + org.codehaus.plexus.redback.rbac.RBACManager + memory + rbacManager + + + + + + org.codehaus.plexus.redback.role.processor.RoleModelProcessor + default + org.codehaus.plexus.redback.role.processor.DefaultRoleModelProcessor + DefaultRoleModelProcessor: inserts the components of the model that can be populated into the rbac manager + + + org.codehaus.plexus.redback.rbac.RBACManager + memory + rbacManager + + + + + + org.codehaus.plexus.redback.role.template.RoleTemplateProcessor + default + org.codehaus.plexus.redback.role.template.DefaultRoleTemplateProcessor + DefaultRoleTemplateProcessor: inserts the components of a template into the rbac manager + + + org.codehaus.plexus.redback.rbac.RBACManager + memory + rbacManager + + + + + + diff --git a/archiva-web/archiva-security/src/test/resources/org/apache/maven/archiva/security/RoleManagerTest.xml b/archiva-web/archiva-security/src/test/resources/org/apache/maven/archiva/security/RoleManagerTest.xml index 65ede8171..d45485407 100644 --- a/archiva-web/archiva-security/src/test/resources/org/apache/maven/archiva/security/RoleManagerTest.xml +++ b/archiva-web/archiva-security/src/test/resources/org/apache/maven/archiva/security/RoleManagerTest.xml @@ -34,7 +34,7 @@ - + org.codehaus.plexus.redback.role.processor.RoleModelProcessor default org.codehaus.plexus.redback.role.processor.DefaultRoleModelProcessor @@ -47,6 +47,7 @@ + org.codehaus.plexus.redback.role.template.RoleTemplateProcessor default @@ -60,5 +61,45 @@ + + org.codehaus.plexus.redback.system.check.EnvironmentCheck + required-roles + org.apache.maven.archiva.security.ArchivaStandardRolesCheck + ArchivaStandardRolesCheck tests for the existance of expected / standard roles and permissions. + + + org.codehaus.plexus.redback.rbac.RBACManager + memory + rbacManager + + + + + + org.apache.maven.archiva.security.SecurityStartup + org.apache.maven.archiva.security.SecurityStartup + SecurityStartup + + + org.codehaus.plexus.redback.role.RoleManager + default + roleManager + + + org.codehaus.plexus.redback.rbac.RBACManager + memory + rbacManager + + + org.codehaus.plexus.redback.system.check.EnvironmentCheck + checkers + + + org.apache.maven.archiva.configuration.ArchivaConfiguration + archivaConfiguration + + + + diff --git a/archiva-web/archiva-security/src/test/resources/org/apache/maven/archiva/security/SecurityStartupTest.xml b/archiva-web/archiva-security/src/test/resources/org/apache/maven/archiva/security/SecurityStartupTest.xml new file mode 100644 index 000000000..a29933aef --- /dev/null +++ b/archiva-web/archiva-security/src/test/resources/org/apache/maven/archiva/security/SecurityStartupTest.xml @@ -0,0 +1,210 @@ + + + + + + org.codehaus.plexus.redback.system.check.EnvironmentCheck + required-roles + org.apache.maven.archiva.security.ArchivaStandardRolesCheck + ArchivaStandardRolesCheck tests for the existance of expected / standard roles and permissions. + + + org.codehaus.plexus.redback.rbac.RBACManager + memory + rbacManager + + + + + + org.apache.maven.archiva.security.SecurityStartup + org.apache.maven.archiva.security.SecurityStartup + SecurityStartup + + + org.apache.maven.archiva.security.UserRepositories + userRepos + + + org.codehaus.plexus.redback.rbac.RBACManager + memory + rbacManager + + + org.codehaus.plexus.redback.system.check.EnvironmentCheck + checkers + + + org.apache.maven.archiva.configuration.ArchivaConfiguration + archivaConfiguration + + + + + + org.apache.maven.archiva.security.UserRepositories + default + org.apache.maven.archiva.security.DefaultUserRepositories + DefaultUserRepositories + + + org.codehaus.plexus.redback.system.SecuritySystem + testable + securitySystem + + + org.codehaus.plexus.redback.rbac.RBACManager + memory + rbacManager + + + org.codehaus.plexus.redback.role.RoleManager + default + roleManager + + + + + + org.codehaus.plexus.redback.role.template.RoleTemplateProcessor + default + org.codehaus.plexus.redback.role.template.DefaultRoleTemplateProcessor + DefaultRoleTemplateProcessor: inserts the components of a template into the rbac manager + + + org.codehaus.plexus.redback.rbac.RBACManager + memory + rbacManager + + + + + + org.codehaus.plexus.redback.role.processor.RoleModelProcessor + default + org.codehaus.plexus.redback.role.processor.DefaultRoleModelProcessor + DefaultRoleModelProcessor: inserts the components of the model that can be populated into the rbac manager + + + org.codehaus.plexus.redback.rbac.RBACManager + memory + rbacManager + + + + + + org.codehaus.plexus.redback.role.RoleManager + default + org.codehaus.plexus.redback.role.DefaultRoleManager + singleton + RoleProfileManager: + + + org.codehaus.plexus.redback.role.merger.RoleModelMerger + default + modelMerger + + + org.codehaus.plexus.redback.role.validator.RoleModelValidator + default + modelValidator + + + org.codehaus.plexus.redback.role.processor.RoleModelProcessor + default + modelProcessor + + + org.codehaus.plexus.redback.role.template.RoleTemplateProcessor + default + templateProcessor + + + org.codehaus.plexus.redback.rbac.RBACManager + memory + rbacManager + + + org.codehaus.plexus.PlexusContainer + container + + + + + + org.codehaus.plexus.redback.system.SecuritySystem + testable + org.codehaus.plexus.redback.system.DefaultSecuritySystem + DefaultSecuritySystem: + + + org.codehaus.plexus.redback.authentication.AuthenticationManager + authnManager + + + org.codehaus.plexus.redback.authorization.Authorizer + rbac + authorizer + + + org.codehaus.plexus.redback.users.UserManager + memory + userManager + + + org.codehaus.plexus.redback.keys.KeyManager + memory + keyManager + + + org.codehaus.plexus.redback.policy.UserSecurityPolicy + policy + + + + + + org.codehaus.plexus.redback.authorization.Authorizer + rbac + org.codehaus.plexus.redback.authorization.rbac.RbacAuthorizer + RbacAuthorizer: + + + org.codehaus.plexus.redback.rbac.RBACManager + memory + manager + + + org.codehaus.plexus.redback.users.UserManager + memory + userManager + + + org.codehaus.plexus.redback.authorization.rbac.evaluator.PermissionEvaluator + default + evaluator + + + org.codehaus.plexus.redback.configuration.UserConfiguration + default + config + + + + + + org.codehaus.plexus.redback.authorization.rbac.evaluator.PermissionEvaluator + default + org.codehaus.plexus.redback.authorization.rbac.evaluator.DefaultPermissionEvaluator + + + org.codehaus.plexus.redback.users.UserManager + memory + userManager + + + + + +