fix assignment of administrator privileges by configuration

This commit is contained in:
Sebastian Sdorra
2019-01-18 08:35:34 +01:00
parent b2e1dcf0e9
commit 36ea444e69
2 changed files with 77 additions and 12 deletions

View File

@@ -51,6 +51,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import sonia.scm.cache.Cache; import sonia.scm.cache.Cache;
import sonia.scm.cache.CacheManager; import sonia.scm.cache.CacheManager;
import sonia.scm.config.ScmConfiguration;
import sonia.scm.group.GroupNames; import sonia.scm.group.GroupNames;
import sonia.scm.group.GroupPermissions; import sonia.scm.group.GroupPermissions;
import sonia.scm.plugin.Extension; import sonia.scm.plugin.Extension;
@@ -76,9 +77,6 @@ import java.util.Set;
public class DefaultAuthorizationCollector implements AuthorizationCollector public class DefaultAuthorizationCollector implements AuthorizationCollector
{ {
// TODO move to util class
private static final String SEPARATOR = System.getProperty("line.separator", "\n");
/** Field description */ /** Field description */
private static final String ADMIN_PERMISSION = "*"; private static final String ADMIN_PERMISSION = "*";
@@ -98,14 +96,16 @@ public class DefaultAuthorizationCollector implements AuthorizationCollector
* *
* *
* *
* @param configuration
* @param cacheManager * @param cacheManager
* @param repositoryDAO * @param repositoryDAO
* @param securitySystem * @param securitySystem
*/ */
@Inject @Inject
public DefaultAuthorizationCollector(CacheManager cacheManager, public DefaultAuthorizationCollector(ScmConfiguration configuration, CacheManager cacheManager,
RepositoryDAO repositoryDAO, SecuritySystem securitySystem) RepositoryDAO repositoryDAO, SecuritySystem securitySystem)
{ {
this.configuration = configuration;
this.cache = cacheManager.getCache(CACHE_NAME); this.cache = cacheManager.getCache(CACHE_NAME);
this.repositoryDAO = repositoryDAO; this.repositoryDAO = repositoryDAO;
this.securitySystem = securitySystem; this.securitySystem = securitySystem;
@@ -239,7 +239,7 @@ public class DefaultAuthorizationCollector implements AuthorizationCollector
Set<String> roles; Set<String> roles;
Set<String> permissions; Set<String> permissions;
if (user.isAdmin()) if (isAdmin(user, groups))
{ {
if (logger.isDebugEnabled()) if (logger.isDebugEnabled())
{ {
@@ -270,6 +270,37 @@ public class DefaultAuthorizationCollector implements AuthorizationCollector
return info; return info;
} }
private boolean isAdmin(User user, GroupNames groups) {
boolean admin = user.isAdmin();
if (admin) {
logger.debug("user {} is marked as admin, because of the user flag", user.getName());
return true;
}
if (isUserAdminInConfiguration(user)) {
logger.debug("user {} is marked as admin, because of the admin user configuration", user.getName());
return true;
}
return isUserAdminInGroupConfiguration(user, groups);
}
private boolean isUserAdminInGroupConfiguration(User user, GroupNames groups) {
Set<String> adminGroups = configuration.getAdminGroups();
if (adminGroups != null && groups != null) {
for (String group : groups) {
if (adminGroups.contains(group)) {
logger.debug("user {} is marked as admin, because of the admin group configuration for group {}", user.getName(), group);
return true;
}
}
}
return false;
}
private boolean isUserAdminInConfiguration(User user) {
Set<String> adminUsers = configuration.getAdminUsers();
return adminUsers != null && adminUsers.contains(user.getName());
}
private String getGroupAutocompletePermission() { private String getGroupAutocompletePermission() {
return GroupPermissions.autocomplete().asShiroString(); return GroupPermissions.autocomplete().asShiroString();
} }
@@ -373,6 +404,8 @@ public class DefaultAuthorizationCollector implements AuthorizationCollector
//~--- fields --------------------------------------------------------------- //~--- fields ---------------------------------------------------------------
private final ScmConfiguration configuration;
/** authorization cache */ /** authorization cache */
private final Cache<CacheKey, AuthorizationInfo> cache; private final Cache<CacheKey, AuthorizationInfo> cache;

View File

@@ -34,6 +34,7 @@ package sonia.scm.security;
import com.github.sdorra.shiro.ShiroRule; import com.github.sdorra.shiro.ShiroRule;
import com.github.sdorra.shiro.SubjectAware; import com.github.sdorra.shiro.SubjectAware;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import org.apache.shiro.authz.AuthorizationInfo; import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo; import org.apache.shiro.authz.SimpleAuthorizationInfo;
@@ -49,6 +50,7 @@ import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnitRunner; import org.mockito.junit.MockitoJUnitRunner;
import sonia.scm.cache.Cache; import sonia.scm.cache.Cache;
import sonia.scm.cache.CacheManager; import sonia.scm.cache.CacheManager;
import sonia.scm.config.ScmConfiguration;
import sonia.scm.group.GroupNames; import sonia.scm.group.GroupNames;
import sonia.scm.repository.PermissionType; import sonia.scm.repository.PermissionType;
import sonia.scm.repository.Repository; import sonia.scm.repository.Repository;
@@ -76,6 +78,8 @@ import static org.mockito.Mockito.when;
@RunWith(MockitoJUnitRunner.class) @RunWith(MockitoJUnitRunner.class)
public class DefaultAuthorizationCollectorTest { public class DefaultAuthorizationCollectorTest {
private ScmConfiguration configuration;
@Mock @Mock
private Cache cache; private Cache cache;
@@ -99,8 +103,38 @@ public class DefaultAuthorizationCollectorTest {
@Before @Before
public void setUp(){ public void setUp(){
when(cacheManager.getCache(Mockito.any(String.class))).thenReturn(cache); when(cacheManager.getCache(Mockito.any(String.class))).thenReturn(cache);
configuration = new ScmConfiguration();
collector = new DefaultAuthorizationCollector(configuration, cacheManager, repositoryDAO, securitySystem);
}
collector = new DefaultAuthorizationCollector(cacheManager, repositoryDAO, securitySystem); @Test
@SubjectAware(
configuration = "classpath:sonia/scm/shiro-001.ini"
)
public void shouldGetAdminPrivilegedByConfiguration() {
configuration.setAdminUsers(ImmutableSet.of("trillian"));
authenticate(UserTestData.createTrillian(), "main");
AuthorizationInfo authInfo = collector.collect();
assertIsAdmin(authInfo);
}
private void assertIsAdmin(AuthorizationInfo authInfo) {
assertThat(authInfo.getRoles(), Matchers.containsInAnyOrder(Role.USER, Role.ADMIN));
assertThat(authInfo.getObjectPermissions(), nullValue());
assertThat(authInfo.getStringPermissions(), Matchers.contains("*"));
}
@Test
@SubjectAware(
configuration = "classpath:sonia/scm/shiro-001.ini"
)
public void shouldGetAdminPrivilegedByGroupConfiguration() {
configuration.setAdminGroups(ImmutableSet.of("heartOfGold"));
authenticate(UserTestData.createTrillian(), "heartOfGold");
AuthorizationInfo authInfo = collector.collect();
assertIsAdmin(authInfo);
} }
/** /**
@@ -142,7 +176,7 @@ public class DefaultAuthorizationCollectorTest {
public void testCollectWithCache() { public void testCollectWithCache() {
authenticate(UserTestData.createTrillian(), "main"); authenticate(UserTestData.createTrillian(), "main");
AuthorizationInfo authInfo = collector.collect(); collector.collect();
verify(cache).put(any(), any()); verify(cache).put(any(), any());
} }
@@ -176,9 +210,7 @@ public class DefaultAuthorizationCollectorTest {
authenticate(trillian, "main"); authenticate(trillian, "main");
AuthorizationInfo authInfo = collector.collect(); AuthorizationInfo authInfo = collector.collect();
assertThat(authInfo.getRoles(), Matchers.containsInAnyOrder(Role.USER, Role.ADMIN)); assertIsAdmin(authInfo);
assertThat(authInfo.getObjectPermissions(), nullValue());
assertThat(authInfo.getStringPermissions(), Matchers.contains("*"));
} }
/** /**
@@ -238,7 +270,7 @@ public class DefaultAuthorizationCollectorTest {
} }
/** /**
* Tests {@link AuthorizationCollector#invalidateCache(sonia.scm.security.AuthorizationChangedEvent)}. * Tests {@link DefaultAuthorizationCollector#invalidateCache(sonia.scm.security.AuthorizationChangedEvent)}.
*/ */
@Test @Test
public void testInvalidateCache() { public void testInvalidateCache() {