Commit 2f577e02 authored by etj's avatar etj
Browse files

[GEOS-7350] GeoFence - Workspace administration rights (2.8.x backport)

parent a64b3899
/*
* Copyright (C) 2007 - 2014 GeoSolutions S.A.S.
* Copyright (C) 2007 - 2015 GeoSolutions S.A.S.
* http://www.geo-solutions.it
*
* GPLv3 + Classpath exception
......@@ -104,6 +104,7 @@ import com.vividsolutions.jts.io.WKTReader;
* Makes GeoServer use the Geofence to assess data access rules
*
* @author Andrea Aime - GeoSolutions
* @author Emanuele Tajariol- GeoSolutions
*/
public class GeofenceAccessManager implements ResourceAccessManager, DispatcherCallback
{
......@@ -157,7 +158,8 @@ public class GeofenceAccessManager implements ResourceAccessManager, DispatcherC
}
@Override
public WorkspaceAccessLimits getAccessLimits(Authentication user, WorkspaceInfo workspace) {
public WorkspaceAccessLimits getAccessLimits(Authentication user, WorkspaceInfo workspace)
{
LOGGER.log(Level.FINE, "Getting access limits for workspace {0}", workspace.getName());
if ((user != null) && !(user instanceof AnonymousAuthenticationToken)) {
......@@ -168,13 +170,50 @@ public class GeofenceAccessManager implements ResourceAccessManager, DispatcherC
return new WorkspaceAccessLimits(DEFAULT_CATALOG_MODE, true, true);
}
return new WorkspaceAccessLimits(DEFAULT_CATALOG_MODE, true, configurationManager.getConfiguration().isGrantWriteToWorkspacesToAuthenticatedUsers());
boolean canWrite = configurationManager.getConfiguration().isGrantWriteToWorkspacesToAuthenticatedUsers();
boolean canAdmin = isWorkspaceAdmin(user, workspace.getName());
return new WorkspaceAccessLimits(DEFAULT_CATALOG_MODE, true, canWrite, canAdmin);
}
// further logic disabled because of https://github.com/geosolutions-it/geofence/issues/6
return new WorkspaceAccessLimits(DEFAULT_CATALOG_MODE, true, false);
}
/**
* We expect the user not to be null and not to be admin
*/
private boolean isWorkspaceAdmin(Authentication user, String workspaceName)
{
LOGGER.log(Level.FINE, "Getting admin auth for Workspace {0}", workspaceName);
// get the request infos
RuleFilter ruleFilter = new RuleFilter(RuleFilter.SpecialFilterType.ANY);
ruleFilter.setInstance(configurationManager.getConfiguration().getInstanceName());
ruleFilter.setWorkspace(workspaceName);
ruleFilter.setUser(user.getName());
String sourceAddress = retrieveCallerIpAddress();
if(sourceAddress != null) {
ruleFilter.setSourceAddress(sourceAddress);
} else {
LOGGER.log(Level.WARNING, "No source IP address found");
ruleFilter.setSourceAddress(RuleFilter.SpecialFilterType.DEFAULT);
}
if(LOGGER.isLoggable(Level.FINE)) {
LOGGER.log(Level.FINE, "AdminAuth filter: {0}", ruleFilter);
}
AccessInfo auth = rules.getAdminAuthorization(ruleFilter);
LOGGER.log(Level.FINE, "Admin auth for User:{0} Workspace:{1}: {2}", new Object[]{user.getName(), workspaceName, auth.getAdminRights()});
return auth.getAdminRights();
}
String getSourceAddress(HttpServletRequest http) {
try {
if (http == null) {
......@@ -220,13 +259,13 @@ public class GeofenceAccessManager implements ResourceAccessManager, DispatcherC
}
private WorkspaceAccessLimits buildAccessLimits(WorkspaceInfo workspace, AccessInfo rule) {
if (rule == null) {
return new WorkspaceAccessLimits(DEFAULT_CATALOG_MODE, true, true);
} else {
return new WorkspaceAccessLimits(DEFAULT_CATALOG_MODE, rule.getGrant() == GrantType.ALLOW, rule.getGrant() == GrantType.ALLOW);
}
}
// private WorkspaceAccessLimits buildAccessLimits(WorkspaceInfo workspace, AccessInfo rule) {
// if (rule == null) {
// return new WorkspaceAccessLimits(DEFAULT_CATALOG_MODE, true, true);
// } else {
// return new WorkspaceAccessLimits(DEFAULT_CATALOG_MODE, rule.getGrant() == GrantType.ALLOW, rule.getGrant() == GrantType.ALLOW);
// }
// }
@Override
public StyleAccessLimits getAccessLimits(Authentication user, StyleInfo style)
......
......@@ -58,6 +58,7 @@ public class CachedRuleReader implements RuleReaderService {
private LoadingCache<RuleFilter, AccessInfo> ruleCache;
private LoadingCache<NamePw, AuthUser> userCache;
private LoadingCache<RuleFilter, AccessInfo> authCache;
private final GeoFenceConfigurationManager configurationManager;
......@@ -86,6 +87,7 @@ public class CachedRuleReader implements RuleReaderService {
ruleCache = getCacheBuilder().build(new RuleLoader());
userCache = getCacheBuilder().build(new UserLoader());
authCache = getCacheBuilder().build(new AuthLoader());
}
......@@ -143,6 +145,31 @@ public class CachedRuleReader implements RuleReaderService {
}
}
private class AuthLoader extends CacheLoader<RuleFilter, AccessInfo> {
@Override
public AccessInfo load(RuleFilter filter) throws Exception {
if(LOGGER.isLoggable(Level.FINE))
LOGGER.log(Level.FINE, "Loading {0}", filter);
// the service, when integrated, may modify the filter
RuleFilter clone = filter.clone();
return realRuleReaderService.getAdminAuthorization(clone);
}
@Override
public ListenableFuture<AccessInfo> reload(final RuleFilter filter, AccessInfo accessInfo) throws Exception {
if(LOGGER.isLoggable(Level.FINE))
LOGGER.log(Level.FINE, "Reloading {0}", filter);
// the service, when integrated, may modify the filter
RuleFilter clone = filter.clone();
// this is a sync implementation
AccessInfo ret = realRuleReaderService.getAdminAuthorization(clone);
return Futures.immediateFuture(ret);
}
}
private class UserLoader extends CacheLoader<NamePw, AuthUser> {
@Override
......@@ -175,6 +202,7 @@ public class CachedRuleReader implements RuleReaderService {
LOGGER.log(Level.WARNING, "Forcing cache invalidation");
ruleCache.invalidateAll();
userCache.invalidateAll();
authCache.invalidateAll();
}
/**
......@@ -199,6 +227,7 @@ public class CachedRuleReader implements RuleReaderService {
if(dumpCnt.incrementAndGet() % 10 == 0) {
LOGGER.info("Rules :"+ruleCache.stats());
LOGGER.info("Users :"+userCache.stats());
LOGGER.info("Auth :"+authCache.stats());
LOGGER.fine("params :"+cacheConfiguration);
}
......@@ -209,6 +238,23 @@ public class CachedRuleReader implements RuleReaderService {
}
}
@Override
public AccessInfo getAdminAuthorization(RuleFilter filter) {
// return realRuleReaderService.getAdminAuthorization(filter);
if(LOGGER.isLoggable(Level.FINE)) {
LOGGER.log(Level.FINE, "AdminAuth Request for {0}", filter);
}
try {
return authCache.get(filter);
} catch (ExecutionException ex) {
throw new RuntimeException(ex); // fixme: handle me
}
}
/**
* <B>Deprecated method are not cached.</B>
*
......@@ -254,6 +300,10 @@ public class CachedRuleReader implements RuleReaderService {
return ruleCache.stats();
}
public CacheStats getAdminAuthStats() {
return authCache.stats();
}
public CacheStats getUserStats() {
return userCache.stats();
}
......@@ -262,10 +312,15 @@ public class CachedRuleReader implements RuleReaderService {
return ruleCache.size();
}
public long getAdminAuthCacheSize() {
return authCache.size();
}
public long getUserCacheSize() {
return userCache.size();
}
/**
* May be useful if an external peer doesn't want to use the guava dep.
*/
......@@ -279,6 +334,7 @@ public class CachedRuleReader implements RuleReaderService {
+"["
+ "Rule:"+ruleCache.stats()
+ " User:"+userCache.stats()
+ " Auth:"+authCache.stats()
+ " " + cacheConfiguration
+ "]";
}
......
/*
* Copyright (C) 2007 - 2012 GeoSolutions S.A.S.
* Copyright (C) 2007 - 2015 GeoSolutions S.A.S.
* http://www.geo-solutions.it
*
* GPLv3 + Classpath exception
......@@ -19,14 +19,12 @@
*/
package org.geoserver.geofence.cache.rest;
import com.google.common.base.Objects;
import com.google.common.cache.CacheStats;
import org.geoserver.geofence.cache.CachedRuleReader;
import org.restlet.Context;
import org.restlet.data.Request;
import org.restlet.data.Response;
import org.restlet.resource.Representation;
import org.restlet.resource.Resource;
import org.restlet.resource.StringRepresentation;
......@@ -61,6 +59,18 @@ public class RESTCacheStats extends Resource {
.append(" evictionCount:").append(stats.evictionCount())
.append("] \n");
stats = crr.getAdminAuthStats();
sb.append("AdminAuthStats[")
.append(" size:").append(crr.getCacheSize())
.append("/").append(crr.getCacheInitParams().getSize())
.append(" hitCount:").append(stats.hitCount())
.append(" missCount:").append(stats.missCount())
.append(" loadSuccessCount:").append(stats.loadSuccessCount())
.append(" loadExceptionCount:").append(stats.loadExceptionCount())
.append(" totalLoadTime:").append(stats.totalLoadTime())
.append(" evictionCount:").append(stats.evictionCount())
.append("] \n");
stats = crr.getUserStats();
sb.append("UserStats[")
.append(" size:").append(crr.getUserCacheSize())
......
......@@ -96,6 +96,16 @@
<td wicket:id="rule.evict">-</td>
</tr>
<tr class="even">
<th scope="row"><wicket:message key="adminCache">Admin cache</wicket:message></th>
<td wicket:id="admin.size">-</td>
<td wicket:id="admin.hit">-</td>
<td wicket:id="admin.miss">-</td>
<td wicket:id="admin.loadok">-</td>
<td wicket:id="admin.loadko">-</td>
<td wicket:id="admin.loadtime">-</td>
<td wicket:id="admin.evict">-</td>
</tr>
<tr class="odd">
<th scope="row"><wicket:message key="userCache">User cache</wicket:message></th>
<td wicket:id="user.size">-</td>
<td wicket:id="user.hit">-</td>
......
......@@ -229,6 +229,14 @@ public class GeofencePage extends GeoServerSecuredPage {
private static final String KEY_RULE_LOADTIME = "rule.loadtime";
private static final String KEY_RULE_EVICTION = "rule.evict";
private static final String KEY_ADMIN_SIZE = "admin.size";
private static final String KEY_ADMIN_HIT = "admin.hit";
private static final String KEY_ADMIN_MISS = "admin.miss";
private static final String KEY_ADMIN_LOADOK = "admin.loadok";
private static final String KEY_ADMIN_LOADKO = "admin.loadko";
private static final String KEY_ADMIN_LOADTIME = "admin.loadtime";
private static final String KEY_ADMIN_EVICTION = "admin.evict";
private static final String KEY_USER_SIZE = "user.size";
private static final String KEY_USER_HIT = "user.hit";
private static final String KEY_USER_MISS = "user.miss";
......@@ -248,6 +256,14 @@ public class GeofencePage extends GeoServerSecuredPage {
statsValues.put(KEY_RULE_LOADTIME, ""+cacheRuleReader.getStats().totalLoadTime());
statsValues.put(KEY_RULE_EVICTION, ""+cacheRuleReader.getStats().evictionCount());
statsValues.put(KEY_ADMIN_SIZE, ""+cacheRuleReader.getAdminAuthCacheSize());
statsValues.put(KEY_ADMIN_HIT, ""+cacheRuleReader.getAdminAuthStats().hitCount());
statsValues.put(KEY_ADMIN_MISS, ""+cacheRuleReader.getAdminAuthStats().missCount());
statsValues.put(KEY_ADMIN_LOADOK, ""+cacheRuleReader.getAdminAuthStats().loadSuccessCount());
statsValues.put(KEY_ADMIN_LOADKO, ""+cacheRuleReader.getAdminAuthStats().loadExceptionCount());
statsValues.put(KEY_ADMIN_LOADTIME, ""+cacheRuleReader.getAdminAuthStats().totalLoadTime());
statsValues.put(KEY_ADMIN_EVICTION, ""+cacheRuleReader.getAdminAuthStats().evictionCount());
statsValues.put(KEY_USER_SIZE, ""+cacheRuleReader.getUserCacheSize());
statsValues.put(KEY_USER_HIT, ""+cacheRuleReader.getUserStats().hitCount());
statsValues.put(KEY_USER_MISS, ""+cacheRuleReader.getUserStats().missCount());
......
......@@ -30,6 +30,7 @@ GeofencePage.statsLoadTime=Load time
GeofencePage.statsEvict=Evictions
GeofencePage.ruleCache=Rule cache
GeofencePage.adminCache=Admin auth cache
GeofencePage.userCache=User cache
it.geosolutions.geoserver.authentication.auth.GeoFenceAuthenticationProvider.short=GeoFence
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment