Refactor superuser authentication/login such that permissions are handled more appropriately, allowing access to all parts of the system.
Project: http://git-wip-us.apache.org/repos/asf/usergrid/repo Commit: http://git-wip-us.apache.org/repos/asf/usergrid/commit/079898f4 Tree: http://git-wip-us.apache.org/repos/asf/usergrid/tree/079898f4 Diff: http://git-wip-us.apache.org/repos/asf/usergrid/diff/079898f4 Branch: refs/heads/asf-site Commit: 079898f45cb5eb2e2db1ed5c94a95a3c7dac949f Parents: e6600b8 Author: Michael Russo <mru...@apigee.com> Authored: Sat Sep 10 00:41:36 2016 -0700 Committer: Michael Russo <mru...@apigee.com> Committed: Sat Sep 10 14:34:30 2016 -0700 ---------------------------------------------------------------------- .../security/SecuredResourceFilterFactory.java | 16 ++++-- .../shiro/filters/BasicAuthSecurityFilter.java | 56 +++++++++++++++++++- .../rest/applications/ApplicationDeleteIT.java | 1 - .../usergrid/rest/applications/SecurityIT.java | 2 + .../activities/ActivityResourceIT.java | 5 -- .../usergrid/services/AbstractService.java | 8 +++ 6 files changed, 77 insertions(+), 11 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/usergrid/blob/079898f4/stack/rest/src/main/java/org/apache/usergrid/rest/security/SecuredResourceFilterFactory.java ---------------------------------------------------------------------- diff --git a/stack/rest/src/main/java/org/apache/usergrid/rest/security/SecuredResourceFilterFactory.java b/stack/rest/src/main/java/org/apache/usergrid/rest/security/SecuredResourceFilterFactory.java index 80d9074..d68c9c9 100644 --- a/stack/rest/src/main/java/org/apache/usergrid/rest/security/SecuredResourceFilterFactory.java +++ b/stack/rest/src/main/java/org/apache/usergrid/rest/security/SecuredResourceFilterFactory.java @@ -303,7 +303,7 @@ public class SecuredResourceFilterFactory implements DynamicFeature { logger.trace("OrganizationFilter.authorize"); } - if ( !isPermittedAccessToOrganization( getOrganizationIdentifier() ) ) { + if ( !isPermittedAccessToOrganization( getOrganizationIdentifier() ) && !isServiceAdmin() ) { if (logger.isTraceEnabled()) { logger.trace("No organization access authorized"); } @@ -375,7 +375,7 @@ public class SecuredResourceFilterFactory implements DynamicFeature { throw mappableSecurityException( "unauthorized", "No application guest access authorized" ); } } - if ( !isPermittedAccessToApplication( getApplicationIdentifier() ) ) { + if ( !isPermittedAccessToApplication( getApplicationIdentifier() ) && !isServiceAdmin() ) { throw mappableSecurityException( "unauthorized", "No application access authorized" ); } } @@ -397,7 +397,7 @@ public class SecuredResourceFilterFactory implements DynamicFeature { logger.trace("SystemFilter.authorize"); } try { - if (!isServiceAdmin()) { + if (!isServiceAdmin() && !isBasicAuthServiceAdmin(request)) { if (logger.isTraceEnabled()) { logger.trace("You are not the system admin."); } @@ -468,7 +468,7 @@ public class SecuredResourceFilterFactory implements DynamicFeature { logger.debug( "PathPermissionsFilter.authorize" ); } - if ( isServiceAdmin() ){ + if ( isServiceAdmin() || isBasicAuthServiceAdmin(request) ){ if(logger.isTraceEnabled()){ logger.trace("User is sysadmin. Allowing access."); } @@ -543,6 +543,14 @@ public class SecuredResourceFilterFactory implements DynamicFeature { } } + + + } + + private static boolean isBasicAuthServiceAdmin(ContainerRequestContext request){ + + return request.getSecurityContext().isUserInRole( ROLE_SERVICE_ADMIN ); + } } http://git-wip-us.apache.org/repos/asf/usergrid/blob/079898f4/stack/rest/src/main/java/org/apache/usergrid/rest/security/shiro/filters/BasicAuthSecurityFilter.java ---------------------------------------------------------------------- diff --git a/stack/rest/src/main/java/org/apache/usergrid/rest/security/shiro/filters/BasicAuthSecurityFilter.java b/stack/rest/src/main/java/org/apache/usergrid/rest/security/shiro/filters/BasicAuthSecurityFilter.java index b4c4f19..1b53dd6 100644 --- a/stack/rest/src/main/java/org/apache/usergrid/rest/security/shiro/filters/BasicAuthSecurityFilter.java +++ b/stack/rest/src/main/java/org/apache/usergrid/rest/security/shiro/filters/BasicAuthSecurityFilter.java @@ -86,7 +86,22 @@ public class BasicAuthSecurityFilter extends SecurityFilter { } try { - UserInfo userInfo = management.verifyAdminUserPasswordCredentials(name.toLowerCase(), password); + + UserInfo userInfo = null; + String rawPath = request.getUriInfo().getAbsolutePath().getRawPath(); + // make sure the sysadmin can be provisioned, we've already done a user/pass check + if(rawPath.contains("superuser/setup") || rawPath.contains("database/setup") || + rawPath.contains("database/bootstrap")){ + + // this is used as a hook just to allow the system filter since the database may not be set up + request.setSecurityContext( new SysAdminRoleAuthenticator() ); + return; + + }else { + + // do a proper shiro login so permissions can be leveraged appropriately later on + userInfo = management.verifyAdminUserPasswordCredentials(name.toLowerCase(), password); + } PrincipalCredentialsToken token = PrincipalCredentialsToken .getFromAdminUserInfoAndPassword(userInfo, password, emf.getManagementAppId()); Subject subject = SubjectUtils.getSubject(); @@ -121,4 +136,43 @@ public class BasicAuthSecurityFilter extends SecurityFilter { } } + private static class SysAdminRoleAuthenticator implements SecurityContext { + + private final Principal principal; + + + SysAdminRoleAuthenticator() { + principal = new Principal() { + @Override + public String getName() { + return ROLE_SERVICE_ADMIN; + } + }; + } + + + @Override + public Principal getUserPrincipal() { + return principal; + } + + + @Override + public boolean isUserInRole( String role ) { + return role.equals( ROLE_SERVICE_ADMIN ); + } + + + @Override + public boolean isSecure() { + return false; + } + + + @Override + public String getAuthenticationScheme() { + return SecurityContext.BASIC_AUTH; + } + } + } http://git-wip-us.apache.org/repos/asf/usergrid/blob/079898f4/stack/rest/src/test/java/org/apache/usergrid/rest/applications/ApplicationDeleteIT.java ---------------------------------------------------------------------- diff --git a/stack/rest/src/test/java/org/apache/usergrid/rest/applications/ApplicationDeleteIT.java b/stack/rest/src/test/java/org/apache/usergrid/rest/applications/ApplicationDeleteIT.java index c1301bb..6416cff 100644 --- a/stack/rest/src/test/java/org/apache/usergrid/rest/applications/ApplicationDeleteIT.java +++ b/stack/rest/src/test/java/org/apache/usergrid/rest/applications/ApplicationDeleteIT.java @@ -43,7 +43,6 @@ import static org.junit.Assert.fail; import static org.apache.usergrid.rest.management.organizations.applications .ApplicationResource.CONFIRM_APPLICATION_IDENTIFIER; - public class ApplicationDeleteIT extends AbstractRestIT { private static final Logger logger = LoggerFactory.getLogger(ApplicationDeleteIT.class); http://git-wip-us.apache.org/repos/asf/usergrid/blob/079898f4/stack/rest/src/test/java/org/apache/usergrid/rest/applications/SecurityIT.java ---------------------------------------------------------------------- diff --git a/stack/rest/src/test/java/org/apache/usergrid/rest/applications/SecurityIT.java b/stack/rest/src/test/java/org/apache/usergrid/rest/applications/SecurityIT.java index 510e245..48fbf12 100644 --- a/stack/rest/src/test/java/org/apache/usergrid/rest/applications/SecurityIT.java +++ b/stack/rest/src/test/java/org/apache/usergrid/rest/applications/SecurityIT.java @@ -17,6 +17,7 @@ package org.apache.usergrid.rest.applications; +import net.jcip.annotations.NotThreadSafe; import org.apache.usergrid.rest.test.resource.AbstractRestIT; import org.apache.usergrid.rest.test.resource.model.ApiResponse; import org.apache.usergrid.rest.test.resource.model.Entity; @@ -34,6 +35,7 @@ import static org.junit.Assert.fail; * These tests will execute requests against certain paths (with or without credentials) to ensure access is being * allowed according to the REST and Services permissions defined for the resource. */ +@NotThreadSafe public class SecurityIT extends AbstractRestIT { public SecurityIT() throws Exception {} http://git-wip-us.apache.org/repos/asf/usergrid/blob/079898f4/stack/rest/src/test/java/org/apache/usergrid/rest/applications/collection/activities/ActivityResourceIT.java ---------------------------------------------------------------------- diff --git a/stack/rest/src/test/java/org/apache/usergrid/rest/applications/collection/activities/ActivityResourceIT.java b/stack/rest/src/test/java/org/apache/usergrid/rest/applications/collection/activities/ActivityResourceIT.java index 6e12053..c7f39b2 100644 --- a/stack/rest/src/test/java/org/apache/usergrid/rest/applications/collection/activities/ActivityResourceIT.java +++ b/stack/rest/src/test/java/org/apache/usergrid/rest/applications/collection/activities/ActivityResourceIT.java @@ -17,7 +17,6 @@ package org.apache.usergrid.rest.applications.collection.activities; -import org.apache.usergrid.persistence.index.utils.MapUtils; import org.apache.usergrid.rest.test.resource.AbstractRestIT; import org.apache.usergrid.rest.test.resource.endpoints.CollectionEndpoint; import org.apache.usergrid.rest.test.resource.model.*; @@ -26,8 +25,6 @@ import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.apache.usergrid.utils.UUIDUtils; - import javax.ws.rs.ClientErrorException; import static org.junit.Assert.assertEquals; @@ -35,7 +32,6 @@ import static org.junit.Assert.assertTrue; /** @author tnine */ - public class ActivityResourceIT extends AbstractRestIT { private static final Logger log = LoggerFactory.getLogger( ActivityResourceIT.class ); @@ -43,7 +39,6 @@ public class ActivityResourceIT extends AbstractRestIT { private static final String USER = "edanuff"; - private static boolean groupCreated = false; private CollectionEndpoint groupsResource; private CollectionEndpoint groupActivityResource; private CollectionEndpoint usersResource; http://git-wip-us.apache.org/repos/asf/usergrid/blob/079898f4/stack/services/src/main/java/org/apache/usergrid/services/AbstractService.java ---------------------------------------------------------------------- diff --git a/stack/services/src/main/java/org/apache/usergrid/services/AbstractService.java b/stack/services/src/main/java/org/apache/usergrid/services/AbstractService.java index c627730..6736894 100644 --- a/stack/services/src/main/java/org/apache/usergrid/services/AbstractService.java +++ b/stack/services/src/main/java/org/apache/usergrid/services/AbstractService.java @@ -48,6 +48,7 @@ import rx.Subscriber; import java.util.*; import static org.apache.usergrid.security.shiro.utils.SubjectUtils.getPermissionFromPath; +import static org.apache.usergrid.security.shiro.utils.SubjectUtils.isServiceAdmin; import static org.apache.usergrid.services.ServiceParameter.filter; import static org.apache.usergrid.services.ServiceParameter.mergeQueries; import static org.apache.usergrid.utils.ClassUtils.cast; @@ -1353,6 +1354,13 @@ public abstract class AbstractService implements Service { return; } + if( isServiceAdmin() ){ + if(logger.isDebugEnabled()){ + logger.debug("Subject is the sysadmin, short-circuiting and allowing access"); + } + return; + } + String perm = getPermissionFromPath( em.getApplicationRef().getUuid(), context.getAction().toString().toLowerCase(), path ); boolean permitted = currentUser.isPermitted( perm );