USERGRID-1300: localhost superuser setting
Project: http://git-wip-us.apache.org/repos/asf/usergrid/repo Commit: http://git-wip-us.apache.org/repos/asf/usergrid/commit/7ea48c27 Tree: http://git-wip-us.apache.org/repos/asf/usergrid/tree/7ea48c27 Diff: http://git-wip-us.apache.org/repos/asf/usergrid/diff/7ea48c27 Branch: refs/heads/master Commit: 7ea48c27885da00a9a1d2251702e02bfe8ddf1ef Parents: 3df0779 Author: Mike Dunker <[email protected]> Authored: Tue Jun 14 15:16:39 2016 -0700 Committer: Mike Dunker <[email protected]> Committed: Tue Jun 14 15:16:39 2016 -0700 ---------------------------------------------------------------------- .../main/resources/usergrid-default.properties | 4 +++ .../rest/management/ManagementResource.java | 4 +-- .../shiro/filters/BasicAuthSecurityFilter.java | 19 ++++++++++-- .../management/AccountCreationProps.java | 3 +- .../usergrid/management/ManagementService.java | 6 +++- .../cassandra/AccountCreationPropsImpl.java | 17 +++++++++-- .../cassandra/ManagementServiceImpl.java | 32 ++++++++++++++++---- .../apache/usergrid/security/shiro/Realm.java | 6 ---- .../shiro/principals/AdminUserPrincipal.java | 4 +-- .../usergrid/management/OrganizationIT.java | 2 +- .../cassandra/ManagementServiceIT.java | 6 ++-- 11 files changed, 77 insertions(+), 26 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/usergrid/blob/7ea48c27/stack/config/src/main/resources/usergrid-default.properties ---------------------------------------------------------------------- diff --git a/stack/config/src/main/resources/usergrid-default.properties b/stack/config/src/main/resources/usergrid-default.properties index 0fc31ef..d2141cf 100644 --- a/stack/config/src/main/resources/usergrid-default.properties +++ b/stack/config/src/main/resources/usergrid-default.properties @@ -535,6 +535,10 @@ [email protected] usergrid.sysadmin.login.password=test usergrid.sysadmin.login.allowed=true +# if usergrid.sysadmin.login.allowed=true, only allows sysadmin login if request is localhost +# if usergrid.sysadmin.login.allowed=false, this property has no effect +usergrid.sysadmin.localhost.only=false + # Set admin notification email properties # usergrid.sysadmin.email= http://git-wip-us.apache.org/repos/asf/usergrid/blob/7ea48c27/stack/rest/src/main/java/org/apache/usergrid/rest/management/ManagementResource.java ---------------------------------------------------------------------- diff --git a/stack/rest/src/main/java/org/apache/usergrid/rest/management/ManagementResource.java b/stack/rest/src/main/java/org/apache/usergrid/rest/management/ManagementResource.java index 1aa75ee..c4a921c 100644 --- a/stack/rest/src/main/java/org/apache/usergrid/rest/management/ManagementResource.java +++ b/stack/rest/src/main/java/org/apache/usergrid/rest/management/ManagementResource.java @@ -220,7 +220,7 @@ public class ManagementResource extends AbstractContextResource { // do checking for different grant types if ( GrantType.PASSWORD.toString().equals( grant_type ) ) { try { - user = management.verifyAdminUserPasswordCredentials( username, password ); + user = management.verifyAdminUserPasswordCredentials( username, password, ui ); if ( user != null ) { if (logger.isTraceEnabled()) { @@ -438,7 +438,7 @@ public class ManagementResource extends AbstractContextResource { UserInfo user = null; try { - user = management.verifyAdminUserPasswordCredentials( username, password ); + user = management.verifyAdminUserPasswordCredentials( username, password, ui ); } catch ( Exception e1 ) { // intentionally empty http://git-wip-us.apache.org/repos/asf/usergrid/blob/7ea48c27/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 a5d7272..7d6b40c 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 @@ -25,6 +25,7 @@ import javax.ws.rs.container.ContainerRequestContext; import javax.ws.rs.container.PreMatching; import javax.ws.rs.core.SecurityContext; import javax.ws.rs.ext.Provider; +import java.net.InetAddress; import java.security.Principal; import java.util.Map; @@ -65,11 +66,25 @@ public class BasicAuthSecurityFilter extends SecurityFilter { String sysadmin_login_password = properties.getProperty( "usergrid.sysadmin.login.password" ); boolean sysadmin_login_allowed = Boolean.parseBoolean( properties.getProperty( "usergrid.sysadmin.login.allowed" ) ); - if ( name.equals( sysadmin_login_name ) && password.equals( sysadmin_login_password ) - && sysadmin_login_allowed ) { + boolean sysadmin_localhost_only = + Boolean.parseBoolean( properties.getProperty( "usergrid.sysadmin.localhost.only", "false" ) ); + + boolean is_localhost = false; + try { + is_localhost = InetAddress.getByName(request.getUriInfo().getBaseUri().getHost()).isLoopbackAddress(); + } + catch (Exception e) { + // won't treat as localhost + } + boolean password_match = password.equals( sysadmin_login_password ); + if ( name.equals( sysadmin_login_name ) && (password_match || is_localhost) + && sysadmin_login_allowed && (is_localhost || !sysadmin_localhost_only)) { request.setSecurityContext( new SysAdminRoleAuthenticator() ); if (logger.isTraceEnabled()) { logger.trace("System administrator access allowed"); + if (!password_match) { + logger.trace("Allowed sysadmin password mismatch because accessing via localhost"); + } } } } http://git-wip-us.apache.org/repos/asf/usergrid/blob/7ea48c27/stack/services/src/main/java/org/apache/usergrid/management/AccountCreationProps.java ---------------------------------------------------------------------- diff --git a/stack/services/src/main/java/org/apache/usergrid/management/AccountCreationProps.java b/stack/services/src/main/java/org/apache/usergrid/management/AccountCreationProps.java index 17f2c6a..a5a0751 100644 --- a/stack/services/src/main/java/org/apache/usergrid/management/AccountCreationProps.java +++ b/stack/services/src/main/java/org/apache/usergrid/management/AccountCreationProps.java @@ -75,6 +75,7 @@ public interface AccountCreationProps { String PROPERTIES_SYSADMIN_LOGIN_EMAIL = "usergrid.sysadmin.login.email"; String PROPERTIES_SYSADMIN_LOGIN_NAME = "usergrid.sysadmin.login.name"; String PROPERTIES_SYSADMIN_LOGIN_ALLOWED = "usergrid.sysadmin.login.allowed"; + String PROPERTIES_SYSADMIN_LOCALHOST_ONLY = "usergrid.sysadmin.localhost.only"; String PROPERTIES_ADMIN_SYSADMIN_EMAIL = "usergrid.admin.sysadmin.email"; String PROPERTIES_ORG_SYSADMIN_EMAIL = "usergrid.org.sysadmin.email"; @@ -127,7 +128,7 @@ public interface AccountCreationProps { SuperUser getSuperUser(); interface SuperUser{ - boolean isEnabled(); + boolean isEnabled(String host); String getUsername(); String getEmail(); String getPassword(); http://git-wip-us.apache.org/repos/asf/usergrid/blob/7ea48c27/stack/services/src/main/java/org/apache/usergrid/management/ManagementService.java ---------------------------------------------------------------------- diff --git a/stack/services/src/main/java/org/apache/usergrid/management/ManagementService.java b/stack/services/src/main/java/org/apache/usergrid/management/ManagementService.java index 1d74ec3..481f272 100644 --- a/stack/services/src/main/java/org/apache/usergrid/management/ManagementService.java +++ b/stack/services/src/main/java/org/apache/usergrid/management/ManagementService.java @@ -39,6 +39,8 @@ import org.apache.usergrid.services.ServiceResults; import com.google.common.collect.BiMap; import rx.Observable; +import javax.ws.rs.core.UriInfo; + public interface ManagementService { @@ -268,7 +270,9 @@ public interface ManagementService { boolean verifyAdminUserPassword( UUID userId, String password ) throws Exception; - UserInfo verifyAdminUserPasswordCredentials( String name, String password ) throws Exception; + UserInfo verifyAdminUserPasswordCredentialsOnly( String name, String password ) throws Exception; + + UserInfo verifyAdminUserPasswordCredentials( String name, String password, UriInfo uriInfo ) throws Exception; UserInfo verifyMongoCredentials( String name, String nonce, String key ) throws Exception; http://git-wip-us.apache.org/repos/asf/usergrid/blob/7ea48c27/stack/services/src/main/java/org/apache/usergrid/management/cassandra/AccountCreationPropsImpl.java ---------------------------------------------------------------------- diff --git a/stack/services/src/main/java/org/apache/usergrid/management/cassandra/AccountCreationPropsImpl.java b/stack/services/src/main/java/org/apache/usergrid/management/cassandra/AccountCreationPropsImpl.java index 7c6a091..4077ef9 100644 --- a/stack/services/src/main/java/org/apache/usergrid/management/cassandra/AccountCreationPropsImpl.java +++ b/stack/services/src/main/java/org/apache/usergrid/management/cassandra/AccountCreationPropsImpl.java @@ -17,9 +17,11 @@ package org.apache.usergrid.management.cassandra; +import java.net.InetAddress; import java.util.Enumeration; import java.util.Properties; +import com.amazonaws.util.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.apache.usergrid.management.AccountCreationProps; @@ -131,17 +133,28 @@ public class AccountCreationPropsImpl implements AccountCreationProps { private final String username; private final String email; private final String password; + private final boolean localhostOnly; public SuperUserImpl(Properties properties) { enabled = parseBoolean(properties.getProperty(PROPERTIES_SYSADMIN_LOGIN_ALLOWED)); username = properties.getProperty(PROPERTIES_SYSADMIN_LOGIN_NAME); email = properties.getProperty(PROPERTIES_SYSADMIN_LOGIN_EMAIL); password = properties.getProperty(PROPERTIES_SYSADMIN_LOGIN_PASSWORD); + localhostOnly = parseBoolean(properties.getProperty(PROPERTIES_SYSADMIN_LOCALHOST_ONLY, "false")); } @Override - public boolean isEnabled() { - return superuserEnabled(); + public boolean isEnabled(String host) { + boolean isLocalhost = false; + // if host not passed in, assume not localhost + if (!StringUtils.isNullOrEmpty(host)) { + try { + isLocalhost = InetAddress.getByName(host).isLoopbackAddress(); + } catch (Exception e) { + // will treat as non-localhost + } + } + return superuserEnabled() && (isLocalhost || !localhostOnly); } @Override http://git-wip-us.apache.org/repos/asf/usergrid/blob/7ea48c27/stack/services/src/main/java/org/apache/usergrid/management/cassandra/ManagementServiceImpl.java ---------------------------------------------------------------------- diff --git a/stack/services/src/main/java/org/apache/usergrid/management/cassandra/ManagementServiceImpl.java b/stack/services/src/main/java/org/apache/usergrid/management/cassandra/ManagementServiceImpl.java index 73a56c8..bf20c6d 100644 --- a/stack/services/src/main/java/org/apache/usergrid/management/cassandra/ManagementServiceImpl.java +++ b/stack/services/src/main/java/org/apache/usergrid/management/cassandra/ManagementServiceImpl.java @@ -27,6 +27,7 @@ import com.google.inject.Injector; import org.apache.commons.codec.digest.DigestUtils; import org.apache.commons.lang.text.StrSubstitutor; import org.apache.shiro.UnavailableSecurityManagerException; +import org.apache.shiro.authc.ExcessiveAttemptsException; import org.apache.usergrid.corepersistence.service.AggregationService; import org.apache.usergrid.corepersistence.service.AggregationServiceFactory; import org.apache.usergrid.corepersistence.service.ApplicationService; @@ -76,6 +77,7 @@ import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import rx.Observable; +import javax.ws.rs.core.UriInfo; import java.nio.ByteBuffer; import java.util.*; import java.util.Map.Entry; @@ -357,13 +359,13 @@ public class ManagementServiceImpl implements ManagementService { logger.warn( "Test app creation disabled" ); } - if ( superuserEnabled() ) { + if ( superuserShouldBeProvisioned() ) { provisionSuperuser(); } } - public boolean superuserEnabled() { + public boolean superuserShouldBeProvisioned() { boolean superuser_enabled = getBooleanProperty( PROPERTIES_SYSADMIN_LOGIN_ALLOWED ); String superuser_username = properties.getProperty( PROPERTIES_SYSADMIN_LOGIN_NAME ); String superuser_email = properties.getProperty( PROPERTIES_SYSADMIN_LOGIN_EMAIL ); @@ -1347,10 +1349,27 @@ public class ManagementServiceImpl implements ManagementService { @Override - public UserInfo verifyAdminUserPasswordCredentials( String name, String password ) throws Exception { + public UserInfo verifyAdminUserPasswordCredentials( String name, String password, UriInfo uriInfo ) throws Exception { + // uriInfo should not be null + Preconditions.checkArgument(uriInfo != null, "uriInfo parameter should not be null"); + + return verifyAdminUserPasswordCredentialsInternal(name, password, uriInfo); + } + + + @Override + public UserInfo verifyAdminUserPasswordCredentialsOnly( String name, String password ) throws Exception { + return verifyAdminUserPasswordCredentialsInternal(name, password, null); + } + + + private UserInfo verifyAdminUserPasswordCredentialsInternal( String name, String password, UriInfo uriInfo) + throws Exception { + + // null UriInfo means assume not a localhost request if(logger.isTraceEnabled()){ - logger.trace("verifyAdminUserPasswordCredentials for {}", name); + logger.trace("verifyAdminUserPasswordCredentialsInternal for {}", name); } User user = findUserEntity( smf.getManagementAppId(), name ); @@ -1361,7 +1380,8 @@ public class ManagementServiceImpl implements ManagementService { if ( verify( smf.getManagementAppId(), user.getUuid(), password ) ) { UserInfo userInfo = getUserInfo( smf.getManagementAppId(), user ); - boolean userIsSuperAdmin = properties.getSuperUser().isEnabled() + boolean userIsSuperAdmin = + properties.getSuperUser().isEnabled(uriInfo != null ? uriInfo.getBaseUri().getHost() : null) && properties.getSuperUser().getEmail().equals(userInfo.getEmail()); boolean testUserEnabled = parseBoolean( properties.getProperty( PROPERTIES_SETUP_TEST_ACCOUNT ) ); @@ -1634,7 +1654,7 @@ public class ManagementServiceImpl implements ManagementService { Map<UUID, String> organizations; AccountCreationProps.SuperUser superUser = properties.getSuperUser(); - if ( superUser.isEnabled() && superUser.getUsername().equals( user.getUsername() ) ) { + if ( superUser.isEnabled(null) && superUser.getUsername().equals( user.getUsername() ) ) { int maxOrganizations = this.getAccountCreationProps().getMaxOrganizationsForSuperUserLogin(); organizations = buildOrgBiMap( getOrganizations( null, maxOrganizations ) ); } http://git-wip-us.apache.org/repos/asf/usergrid/blob/7ea48c27/stack/services/src/main/java/org/apache/usergrid/security/shiro/Realm.java ---------------------------------------------------------------------- diff --git a/stack/services/src/main/java/org/apache/usergrid/security/shiro/Realm.java b/stack/services/src/main/java/org/apache/usergrid/security/shiro/Realm.java index 4381f01..c8ca812 100644 --- a/stack/services/src/main/java/org/apache/usergrid/security/shiro/Realm.java +++ b/stack/services/src/main/java/org/apache/usergrid/security/shiro/Realm.java @@ -56,12 +56,6 @@ public class Realm extends AuthorizingRealm { private TokenService tokens; - @Value( "${" + PROPERTIES_SYSADMIN_LOGIN_ALLOWED + "}" ) - private boolean superUserEnabled; - @Value( "${" + AccountCreationProps.PROPERTIES_SYSADMIN_LOGIN_NAME + ":admin}" ) - private String superUser; - - public Realm() { setCredentialsMatcher(new AllowAllCredentialsMatcher()); setPermissionResolver(new CustomPermissionResolver()); http://git-wip-us.apache.org/repos/asf/usergrid/blob/7ea48c27/stack/services/src/main/java/org/apache/usergrid/security/shiro/principals/AdminUserPrincipal.java ---------------------------------------------------------------------- diff --git a/stack/services/src/main/java/org/apache/usergrid/security/shiro/principals/AdminUserPrincipal.java b/stack/services/src/main/java/org/apache/usergrid/security/shiro/principals/AdminUserPrincipal.java index a594d1e..fd4f0c5 100644 --- a/stack/services/src/main/java/org/apache/usergrid/security/shiro/principals/AdminUserPrincipal.java +++ b/stack/services/src/main/java/org/apache/usergrid/security/shiro/principals/AdminUserPrincipal.java @@ -66,9 +66,9 @@ public class AdminUserPrincipal extends UserPrincipal { ApplicationInfo application = null; boolean superUserEnabled = false; - final String s = management.getProperties().getProperty( + final String sysadminLoginAllowedProp = management.getProperties().getProperty( AccountCreationProps.PROPERTIES_SYSADMIN_LOGIN_ALLOWED); - if ( s != null && "true".equalsIgnoreCase(s.trim())) { + if ( sysadminLoginAllowedProp != null && "true".equalsIgnoreCase(sysadminLoginAllowedProp.trim())) { superUserEnabled = true; } http://git-wip-us.apache.org/repos/asf/usergrid/blob/7ea48c27/stack/services/src/test/java/org/apache/usergrid/management/OrganizationIT.java ---------------------------------------------------------------------- diff --git a/stack/services/src/test/java/org/apache/usergrid/management/OrganizationIT.java b/stack/services/src/test/java/org/apache/usergrid/management/OrganizationIT.java index 9d20dcb..44599a6 100644 --- a/stack/services/src/test/java/org/apache/usergrid/management/OrganizationIT.java +++ b/stack/services/src/test/java/org/apache/usergrid/management/OrganizationIT.java @@ -103,7 +103,7 @@ public class OrganizationIT { setup.getEntityIndex().refresh(CpNamingUtils.MANAGEMENT_APPLICATION_ID); - UserInfo u = setup.getMgmtSvc().verifyAdminUserPasswordCredentials( + UserInfo u = setup.getMgmtSvc().verifyAdminUserPasswordCredentialsOnly( organization.getOwner().getUuid().toString(), "test" ); assertNotNull( u ); http://git-wip-us.apache.org/repos/asf/usergrid/blob/7ea48c27/stack/services/src/test/java/org/apache/usergrid/management/cassandra/ManagementServiceIT.java ---------------------------------------------------------------------- diff --git a/stack/services/src/test/java/org/apache/usergrid/management/cassandra/ManagementServiceIT.java b/stack/services/src/test/java/org/apache/usergrid/management/cassandra/ManagementServiceIT.java index 6179a6d..83ceae9 100644 --- a/stack/services/src/test/java/org/apache/usergrid/management/cassandra/ManagementServiceIT.java +++ b/stack/services/src/test/java/org/apache/usergrid/management/cassandra/ManagementServiceIT.java @@ -480,15 +480,15 @@ public class ManagementServiceIT { EntityManager em = setup.getEmf().getEntityManager( setup.getSmf().getManagementAppId() ); setup.getEntityIndex().refresh(applicationId); - UserInfo authedUser = setup.getMgmtSvc().verifyAdminUserPasswordCredentials( username, password ); + UserInfo authedUser = setup.getMgmtSvc().verifyAdminUserPasswordCredentialsOnly( username, password ); assertEquals( adminUser.getUuid(), authedUser.getUuid() ); - authedUser = setup.getMgmtSvc().verifyAdminUserPasswordCredentials( adminUser.getEmail(), password ); + authedUser = setup.getMgmtSvc().verifyAdminUserPasswordCredentialsOnly( adminUser.getEmail(), password ); assertEquals( adminUser.getUuid(), authedUser.getUuid() ); - authedUser = setup.getMgmtSvc().verifyAdminUserPasswordCredentials( adminUser.getUuid().toString(), password ); + authedUser = setup.getMgmtSvc().verifyAdminUserPasswordCredentialsOnly( adminUser.getUuid().toString(), password ); assertEquals( adminUser.getUuid(), authedUser.getUuid() ); }
