This commit is contained in:
Manuele Simi 2009-05-27 19:53:23 +00:00
parent ff45baf3b1
commit d8a7203a39
14 changed files with 552 additions and 23 deletions

30
etc/ResourceFilters.xml Normal file
View File

@ -0,0 +1,30 @@
<Resource>
<ID/>
<Type>GenericResource</Type>
<Profile>
<SecondaryType>ISFilters</SecondaryType>
<Name>ISFilters</Name>
<Description>Filtering rules applied on the IS at GCUBEResource registration time</Description>
<Body>
<Filters>
<!-- <Filter resourceType="GHN">
<Target>Site/Domain</Target>
<Value>nyc.res.rr.com</Value>
<Operation>exclude</Operation>
</Filter>
-->
<Filter resourceType="GHN">
<Target>GHNDescription/Name</Target>
<Value>cpe-66-65-101-197.nyc.res.rr.com</Value>
<Operation>exclude</Operation>
</Filter>
<Filter resourceType="RunningInstance">
<Target>AccessPoint/RunningInstanceInterfaces/Endpoint</Target>
<Value>nyc.res.rr.com</Value>
<Operation>exclude_if_contains</Operation>
</Filter>
</Filters>
</Body>
</Profile>
</Resource>

View File

@ -18,9 +18,11 @@
<!-- Lifetime for temporary resources, after this period temporary resources are destroyed-->
<environment
name="temporaryResourceLifetimeInMs"
value="240000"
value="480000"
type="java.lang.Long"
override="false" />
<!--
<environment
@ -76,7 +78,7 @@
<name>resourceClass</name>
<value>org.gcube.informationsystem.registry.impl.state.ProfileResource</value>
</parameter>
<parameter>
<parameter>
<name>persistenceDelegateClass</name>
<value>org.gcube.informationsystem.registry.impl.persistence.RegistryPersistenceDelegate</value>
</parameter>
@ -84,8 +86,7 @@
<name>sweeperDelay</name>
<value>10000</value>
</parameter>
</resourceParams>
</resource>

View File

@ -34,12 +34,12 @@
<PortType>
<Name>gcube/informationsystem/registry/RegistryFactory</Name>
<Security/>
<WSDL/>
<WSDL/>
</PortType>
<PortType>
<Name>gcube/informationsystem/registry/Registry</Name>
<Security/>
<WSDL/>
<WSDL/>
</PortType>
</Main>
<Software>

View File

@ -5,7 +5,7 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<!-- renewal registration time -->
<RefreshIntervalSecs>600</RefreshIntervalSecs>
<RefreshIntervalSecs>60</RefreshIntervalSecs>
<Content xsi:type="agg:AggregatorContent"
xmlns:agg="http://mds.globus.org/aggregator/types">
<agg:AggregatorConfig xsi:type="agg:AggregatorConfig">

View File

@ -206,14 +206,23 @@
<xsd:complexType name="profileAlreadyRegisteredFault">
<xsd:complexContent>
<xsd:extension base="corefaults:GCUBEUnrecoverableFault">
<xsd:sequence>
</xsd:sequence>
<xsd:sequence/>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
<xsd:element name="resourceNotAcceptedFault">
<xsd:complexType>
<xsd:complexContent>
<xsd:extension base="corefaults:GCUBEUnrecoverableFault">
<xsd:sequence/>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
</xsd:element>
</xsd:schema>
</types>
@ -283,6 +292,9 @@
<part name="fault" element="tns:profileAlreadyRegisteredFault"/>
</message>
<message name="resourceNotAcceptedFaultMessage">
<part name="fault" element="tns:resourceNotAcceptedFault"/>
</message>
<!--============================================================
P O R T T Y P E
@ -297,11 +309,13 @@
<output message="tns:CreateResourceResponse"/>
<fault name="fault" message="tns:profileAlreadyRegisteredFaultMessage"></fault>
<fault name="fault" message="tns:schemaValidationFaultMessage"></fault>
<fault name="fault" message="tns:resourceNotAcceptedFaultMessage"></fault>
</operation>
<operation name="updateResource">
<input message="tns:UpdateResourceRequest"/>
<output message="tns:UpdateResourceResponse"/>
<fault name="fault" message="tns:schemaValidationFaultMessage"></fault>
<fault name="fault" message="tns:resourceNotAcceptedFaultMessage"></fault>
</operation>
<operation name="removeResource">
<input message="tns:RemoveResourceRequest"/>
@ -328,7 +342,6 @@
<output message="tns:StartRegistrationResponse"/>
<fault name="fault" message="corefaults:GCUBEFaultMessage"></fault>
</operation>
</portType>

View File

@ -25,6 +25,8 @@ import org.gcube.common.core.utils.logging.GCUBELog;
import org.gcube.informationsystem.registry.impl.contexts.FactoryContext;
import org.gcube.informationsystem.registry.impl.contexts.ProfileContext;
import org.gcube.informationsystem.registry.impl.contexts.ServiceContext;
import org.gcube.informationsystem.registry.impl.filters.FilterManager;
import org.gcube.informationsystem.registry.impl.filters.FilterExecutor.InvalidFilterException;
import org.gcube.informationsystem.registry.impl.state.ProfileResource;
import org.gcube.informationsystem.registry.impl.state.RegistryFactoryResource;
import org.gcube.informationsystem.registry.impl.util.Couple;
@ -36,6 +38,7 @@ import org.gcube.informationsystem.registry.stubs.RegistryProperty;
import org.gcube.informationsystem.registry.stubs.RemoveResourceMessage;
import org.gcube.informationsystem.registry.stubs.RemoveResourceResponse;
import org.gcube.informationsystem.registry.stubs.RemoveScopeInProfileMessage;
import org.gcube.informationsystem.registry.stubs.ResourceNotAcceptedFault;
import org.gcube.informationsystem.registry.stubs.SchemaValidationFault;
import org.gcube.informationsystem.registry.stubs.StartRegistration;
import org.gcube.informationsystem.registry.stubs.StartRegistrationResponse;
@ -122,17 +125,17 @@ public class RegistryFactory extends GCUBEPortType {
* @throws ProfileAlreadyRegisteredFault
*/
@SuppressWarnings("unchecked")
public String createResource(CreateResourceMessage mess) throws SchemaValidationFault,RemoteException,ProfileAlreadyRegisteredFault {
public String createResource(CreateResourceMessage mess) throws SchemaValidationFault,RemoteException,ProfileAlreadyRegisteredFault,ResourceNotAcceptedFault {
GCUBEResource resource=null;
logger.info("CreateResource operation invoked");
logSecurityInfo("createResource");
//logSecurityInfo("createResource");
String profile = mess.getProfile();
if (profile == null || profile.compareTo("") == 0) {
String msg = "Profile file empty";
String msg = "Profile file is empty";
logger.debug(msg);
throw new RemoteException(msg);
}
@ -162,6 +165,17 @@ public class RegistryFactory extends GCUBEPortType {
logger.error("Error trying to load profile", ex);
throw new SchemaValidationFault();
}
//apply resource filter
try {
if (! FilterManager.getExecutor(resource.getType()).accept(resource)) {
logger.warn("Resource "+ resource.getID()+" NOT accepted ");
throw new ResourceNotAcceptedFault();
}
logger.trace("Resource "+ resource.getID()+" accepted ");
} catch (InvalidFilterException e) {
logger.warn("Invalid filter selected, the resource " + resource.getID()+" CANNOT be filtered ");
}
//check if the Resource already exists
if (isResourceCreated(resource.getID())) {
// update the existing resource
@ -235,9 +249,10 @@ public class RegistryFactory extends GCUBEPortType {
* @throws SchemaValidationException Exception
*/
@SuppressWarnings("unchecked")
public UpdateResourceResponse updateResource(UpdateResourceMessage mess) throws RemoteException,SchemaValidationFault,GCUBEFault {
public UpdateResourceResponse updateResource(UpdateResourceMessage mess)
throws RemoteException, SchemaValidationFault, ResourceNotAcceptedFault, GCUBEFault {
logSecurityInfo("updateResource");
//logSecurityInfo("updateResource");
logger.info("UpdateResource operation invoked");
String ID = mess.getUniqueID();
String xmlProfile = mess.getXmlProfile();
@ -263,6 +278,18 @@ public class RegistryFactory extends GCUBEPortType {
try {
resource = ResourceType.valueOf(mess.getType()).getResourceClass();
resource.load(new StringReader(xmlProfile));
//apply resource filter
try {
if (! FilterManager.getExecutor(resource.getType()).accept(resource)) {
logger.warn("Resource "+ resource.getID()+" NOT accepted ");
throw new ResourceNotAcceptedFault();
}
logger.trace("Resource "+ resource.getID()+" accepted ");
} catch (InvalidFilterException e) {
logger.warn("Invalid filter selected, the resource " + resource.getID()+" CANNOT be filtered ");
}
ProfileResource pr= getProfileResource(ID);
pr.updateResource(resource);

View File

@ -0,0 +1,26 @@
package org.gcube.informationsystem.registry.impl.filters;
import java.util.List;
import org.gcube.common.core.resources.GCUBEResource;
/**
* Default filter for {@link GCUBEResource}
* @author Manuele Simi (ISTI-CNR)
*
*/
public class DefaultFilterExecutor extends FilterExecutor {
//private List<Filter> filters = null;
protected DefaultFilterExecutor(List<Filter> filters) {
//this.filters = filters;
}
@Override
public boolean accept(GCUBEResource resource) throws InvalidFilterException {
logger.trace("Accept() on DefaultFilterExecutor invoked");
return true;
}
}

View File

@ -0,0 +1,56 @@
package org.gcube.informationsystem.registry.impl.filters;
public class Filter {
private String target = "";
private String value = "";
private FILTEROPERATION operation = null;
protected enum FILTEROPERATION {exclude, exclude_if_contains}
protected Filter() {}
/**
* @return the target
*/
public String getTarget() {
return this.target;
}
/**
* @param target the target to set
*/
public void setTarget(String target) {
this.target = target;
}
/**
* @return the value
*/
public String getValue() {
return value;
}
/**
* @param value the value to set
*/
public void setValue(String value) {
this.value = value;
}
/**
* @return the operation
*/
public FILTEROPERATION getOperation() {
return operation;
}
/**
* @param operation the operation to set
*/
public void setOperation(FILTEROPERATION operation) {
this.operation = operation;
};
}

View File

@ -0,0 +1,22 @@
package org.gcube.informationsystem.registry.impl.filters;
import org.gcube.common.core.resources.GCUBEResource;
import org.gcube.common.core.utils.logging.GCUBELog;
/**
* Base resource filter
*
* @author Manuele Simi (ISTI-CNR)
*
*/
public abstract class FilterExecutor {
protected GCUBELog logger = new GCUBELog(this);
public abstract boolean accept(GCUBEResource resource) throws InvalidFilterException;
public static class InvalidFilterException extends Exception {
private static final long serialVersionUID = -8353431478801569045L;
public InvalidFilterException(String message) {super(message);}
}
}

View File

@ -0,0 +1,68 @@
package org.gcube.informationsystem.registry.impl.filters;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.gcube.common.core.resources.GCUBEHostingNode;
import org.gcube.common.core.resources.GCUBEResource;
import org.gcube.common.core.resources.GCUBERunningInstance;
import org.gcube.common.core.utils.logging.GCUBELog;
/**
*
* {@link GCUBEResource} filter factory
*
* @author Manuele Simi (ISTI-CNR)
*
*/
public class FilterManager {
protected static GCUBELog logger = new GCUBELog(FilterManager.class);
protected static Map<String, List<Filter>> filters = Collections.synchronizedMap(new HashMap<String, List<Filter>>());
protected static FilterReader reader = null;
/**
* Gets the {@link FilterExecutor} for the given {@link GCUBEResource} type
* @param resourceType the resource type
*
* @return the filter executor
*/
public static FilterExecutor getExecutor(String resourceType) {
initReader();
logger.trace("Executor for " + resourceType + " requested");
logger.trace("Number of filters available: " + getFilters(resourceType).size());
if (resourceType.compareTo(GCUBEHostingNode.TYPE) == 0)
return new GHNFilterExecutor(getFilters(resourceType));
if (resourceType.compareTo(GCUBERunningInstance.TYPE) == 0)
return new RIFilterExecutor(getFilters(resourceType));
return new DefaultFilterExecutor(getFilters(resourceType));
}
/**
* Gets the {@link Filter}s the given {@link GCUBEResource} type
* @param resourceType the resource type
*
* @return the list of filters
*/
protected synchronized static List<Filter> getFilters(String resourceType) {
if (!filters.containsKey(resourceType))
filters.put(resourceType, new ArrayList<Filter>());
return filters.get(resourceType);
}
private synchronized static void initReader() {
if (reader == null) reader = new FilterReader();
}
}

View File

@ -0,0 +1,133 @@
package org.gcube.informationsystem.registry.impl.filters;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.StringReader;
import java.util.Collection;
import java.util.List;
import org.gcube.common.core.contexts.GHNContext;
import org.gcube.common.core.informationsystem.client.AtomicCondition;
import org.gcube.common.core.informationsystem.client.ISClient;
import org.gcube.common.core.informationsystem.client.queries.GCUBEGenericResourceQuery;
import org.gcube.common.core.resources.GCUBEGenericResource;
import org.gcube.common.core.scope.GCUBEScope;
import org.gcube.common.core.utils.logging.GCUBELog;
import org.gcube.informationsystem.registry.impl.contexts.ServiceContext;
import org.gcube.informationsystem.registry.impl.filters.Filter.FILTEROPERATION;
import org.kxml2.io.KXmlParser;
public class FilterReader {
private GCUBEGenericResource resource;
protected GCUBELog logger = new GCUBELog(this);
protected FilterReader() {
if (!this.loadFiltersFromIS(ServiceContext.getContext().getInstance().getScopes().values()))
this.loadFiltersFromFile(ServiceContext.getContext().getFile("ResourceFilters.xml", false));
}
/**
* Loads the ISFilters resource from a file
* @param file the file
*
* @return true if the resource is found and loaded, false otherwise
*/
private boolean loadFiltersFromFile(File file) {
// get the resource implementation
try {
this.resource = GHNContext.getImplementation(GCUBEGenericResource.class);
this.resource.load(new FileReader(file));
this.parseFilters(this.resource.getBody());
return true;
} catch (Exception e) {
try {
logger.error("Unable to load the ISFilters Resource from " + file.getAbsolutePath() ,e);
throw new Exception("Unable to load the ISFilters Resource from " + file.getAbsolutePath());
} catch (Exception e1) {
logger.error("",e1 );
}
}
return false;
}
/**
* Loads the ISFilters resource from the IS
* @param resource the resource to load
*
* @return true if the resource is found and loaded, false otherwise
*/
private boolean loadFiltersFromIS(Collection<GCUBEScope> scopes) {
try {
ISClient client = GHNContext.getImplementation(ISClient.class);
GCUBEGenericResourceQuery query = client.getQuery(GCUBEGenericResourceQuery.class);
query.addAtomicConditions(new AtomicCondition("//SecondaryType", "ISFilters"));
logger.trace(query.toString());
for (GCUBEScope scope : scopes) {
List<GCUBEGenericResource> results = client.execute(query, scope);
if ((results != null) && (results.size() > 0)) {
this.resource = results.get(0);
this.parseFilters(this.resource.getBody());
logger.debug("ISFilters Resource loaded from the IS");
return true;
} else
logger.warn("Unable to load the ISFilters for "+ scope.toString() + " from the IS");
}
} catch (Exception e) {logger.warn("ISFilters not available on the IS", e);}
return false;
}
private void parseFilters(String body) throws Exception {
KXmlParser parser = new KXmlParser();
parser.setInput(new BufferedReader(new StringReader(body)));
loop: while (true) {
try {
switch (parser.next()) {
case KXmlParser.START_TAG:
if (parser.getName().equals("Filter")) {
logger.debug("New filter found for " + parser.getAttributeValue("","resourceType"));
FilterManager.getFilters(parser.getAttributeValue("", "resourceType")).add(this.parseFilter(parser));
}
break;
case KXmlParser.END_TAG: if (parser.getName().equals("Filters")) break loop;
case KXmlParser.END_DOCUMENT: break loop;
}
} catch (Exception e) {
logger.error("",e);
throw new Exception ("Unable to parse the ISFilters body");
}
}
}
private Filter parseFilter(KXmlParser parser) throws Exception {
Filter filter = new Filter();
loop: while (true) {
try {
switch (parser.next()) {
case KXmlParser.START_TAG:
if (parser.getName().equals("Target")) filter.setTarget(parser.nextText().trim());
else if (parser.getName().equals("Value")) filter.setValue((parser.nextText().trim()));
else if (parser.getName().equals("Operation")) filter.setOperation(FILTEROPERATION.valueOf(parser.nextText().trim()));
else parser.nextText();//just skip the text
break;
case KXmlParser.END_TAG: if (parser.getName().equals("Filter")) break loop;
}
} catch (Exception e) {
throw new Exception ("Unable to parse at Filter");
}
}
return filter;
}
}

View File

@ -0,0 +1,73 @@
package org.gcube.informationsystem.registry.impl.filters;
import java.util.List;
import org.gcube.common.core.resources.GCUBEHostingNode;
import org.gcube.common.core.resources.GCUBEResource;
import org.gcube.informationsystem.registry.impl.filters.Filter.FILTEROPERATION;
/**
* Filter for {@link GCUBEHostingNode} resource
*
* @author Manuele Simi (ISTI-CNR)
*
*/
public class GHNFilterExecutor extends FilterExecutor {
private List<Filter> filters = null;
private GCUBEHostingNode node = null;
protected GHNFilterExecutor(List<Filter> filters) {
this.filters = filters;
}
@Override
public boolean accept(GCUBEResource resource) throws InvalidFilterException {
if (resource.getType().compareTo(GCUBEHostingNode.TYPE) != 0) {
throw new InvalidFilterException("Cannot apply " + this.getClass().getName() + " filter to " + resource.getType());
}
this.node = (GCUBEHostingNode) resource;
logger.trace("Applying N." + this.filters.size() + " filters to GHN");
for (Filter filter : this.filters) {
if (!this._accept(filter))
return false;
}
return true;
}
private boolean _accept(Filter filter) {
if ((filter.getTarget().compareToIgnoreCase("Site/Domain") == 0) &&
((filter.getOperation() == FILTEROPERATION.exclude) || (filter.getOperation() == FILTEROPERATION.exclude_if_contains)))
return !this.isExcludedDomain(filter.getValue());
if ((filter.getTarget().compareToIgnoreCase("GHNDescription/Name") == 0) &&
((filter.getOperation() == FILTEROPERATION.exclude) || (filter.getOperation() == FILTEROPERATION.exclude_if_contains)))
return !this.isExcludedHost(filter.getValue());
logger.warn("Target "+ filter.getTarget() +" or Operation " + filter.getOperation().name() + " not supported by the GHNFilter");
return true;
}
private boolean isExcludedHost(String host) {
logger.trace("Checking host " + this.node.getNodeDescription().getName());
if (this.node.getNodeDescription().getName().split(":")[0].compareToIgnoreCase(host) == 0) {
logger.warn("Detected banned hostname " + host + " for GHN " + this.node.getID());
return true;
}
return false;
}
private boolean isExcludedDomain(String domain) {
logger.trace("Checking domain " + this.node.getSite().getDomain());
if (this.node.getSite().getDomain().compareToIgnoreCase(domain) == 0 ) {
logger.warn("Detected banned domain " + domain + " for GHN " + this.node.getID());
return true;
}
return false;
}
}

View File

@ -0,0 +1,83 @@
package org.gcube.informationsystem.registry.impl.filters;
import java.util.List;
import org.gcube.common.core.resources.GCUBERunningInstance;
import org.gcube.common.core.resources.GCUBEResource;
import org.gcube.common.core.resources.runninginstance.Endpoint;
import org.gcube.informationsystem.registry.impl.filters.Filter.FILTEROPERATION;
/**
* Filter for {@link GCUBERunningInstance} resource
*
* @author Manuele Simi (ISTI-CNR)
*
*/
public class RIFilterExecutor extends FilterExecutor {
private List<Filter> filters = null;
private GCUBERunningInstance instance = null;
protected RIFilterExecutor(List<Filter> filters) {
this.filters = filters;
}
@Override
public boolean accept(GCUBEResource resource) throws InvalidFilterException {
if (resource.getType().compareTo(GCUBERunningInstance.TYPE) != 0) {
throw new InvalidFilterException("Cannot apply " + this.getClass().getName() + " filter to " + resource.getType());
}
this.instance = (GCUBERunningInstance) resource;
logger.trace("Applying N." + this.filters.size() + " filters to RI");
for (Filter filter : this.filters) {
if (!this._accept(filter))
return false;
}
return true;
}
private boolean _accept(Filter filter) {
if ((filter.getTarget().compareToIgnoreCase("AccessPoint/RunningInstanceInterfaces/Endpoint") == 0) && (filter.getOperation() == FILTEROPERATION.exclude_if_contains))
return !this.isExcludedIfContainsEPR(filter.getValue());
if ((filter.getTarget().compareToIgnoreCase("AccessPoint/RunningInstanceInterfaces/Endpoint") == 0) && (filter.getOperation() == FILTEROPERATION.exclude))
return !this.isExcludedEPR(filter.getValue());
return true;
}
private boolean isExcludedIfContainsEPR(String value) {
for (Endpoint endpoint: this.instance.getAccessPoint().getRunningInstanceInterfaces().getEndpoint()) {
logger.trace("Checking endpoint " + endpoint.getValue());
if (endpoint.getValue().contains(value)) {
logger.warn("Detected banned EPR " + value + " for RI " + this.instance.getID());
return true;
}
}
return false;
}
private boolean isExcludedEPR(String value) {
for (Endpoint endpoint: this.instance.getAccessPoint().getRunningInstanceInterfaces().getEndpoint()) {
logger.trace("Checking endpoint " + endpoint.getValue());
if (endpoint.getValue().compareToIgnoreCase(value) == 0) {
logger.warn("Detected banned EPR " + value + " for RI " + this.instance.getID());
return true;
}
}
return false;
}
}

View File

@ -11,8 +11,6 @@ import org.gcube.common.core.informationsystem.publisher.ISPublisherException;
import org.gcube.common.core.contexts.GHNContext;
import org.gcube.common.core.resources.GCUBEHostingNode;
import org.gcube.common.core.resources.GCUBEResource;
import org.gcube.common.core.resources.GCUBERunningInstance;
import org.gcube.common.core.resources.GCUBEService;
import org.gcube.common.core.state.GCUBEWSResource;
import org.gcube.common.core.utils.logging.GCUBELog;
@ -147,7 +145,6 @@ public class ProfileResource extends GCUBEWSResource {
public void setProfile(Document profile) {
this.getResourcePropertySet().get(ProfileRP).clear();
this.getResourcePropertySet().get(ProfileRP).add(profile);
//this.getPersistenceDelegate().store(this);
}
/**
@ -168,10 +165,10 @@ public class ProfileResource extends GCUBEWSResource {
* @return true/false
*/
private boolean hasToLive(GCUBEResource resource) {
if (resource.getType().compareTo(GCUBERunningInstance.TYPE)==0 ||
resource.getType().compareTo(GCUBEHostingNode.TYPE)==0 ||
resource.getType().compareTo(GCUBEService.TYPE)==0) return true;
else return false;
if (resource.getType().compareTo(GCUBEHostingNode.TYPE)==0)
return true;
else
return false;
}
/**