diff --git a/1.0/.classpath b/1.0/.classpath new file mode 100644 index 0000000..e43402f --- /dev/null +++ b/1.0/.classpath @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/1.0/.project b/1.0/.project new file mode 100644 index 0000000..ea71595 --- /dev/null +++ b/1.0/.project @@ -0,0 +1,23 @@ + + + authorization-common-client + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.m2e.core.maven2Builder + + + + + + org.eclipse.jdt.core.javanature + org.eclipse.m2e.core.maven2Nature + + diff --git a/1.0/.settings/org.eclipse.core.resources.prefs b/1.0/.settings/org.eclipse.core.resources.prefs new file mode 100644 index 0000000..29abf99 --- /dev/null +++ b/1.0/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,6 @@ +eclipse.preferences.version=1 +encoding//src/main/java=UTF-8 +encoding//src/main/resources=UTF-8 +encoding//src/test/java=UTF-8 +encoding//src/test/resources=UTF-8 +encoding/=UTF-8 diff --git a/1.0/.settings/org.eclipse.jdt.core.prefs b/1.0/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..ec4300d --- /dev/null +++ b/1.0/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,5 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7 +org.eclipse.jdt.core.compiler.compliance=1.7 +org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning +org.eclipse.jdt.core.compiler.source=1.7 diff --git a/1.0/.settings/org.eclipse.m2e.core.prefs b/1.0/.settings/org.eclipse.m2e.core.prefs new file mode 100644 index 0000000..f897a7f --- /dev/null +++ b/1.0/.settings/org.eclipse.m2e.core.prefs @@ -0,0 +1,4 @@ +activeProfiles= +eclipse.preferences.version=1 +resolveWorkspaceProjects=true +version=1 diff --git a/1.0/distro/INSTALL b/1.0/distro/INSTALL new file mode 100644 index 0000000..8d1c8b6 --- /dev/null +++ b/1.0/distro/INSTALL @@ -0,0 +1 @@ + diff --git a/1.0/distro/LICENSE b/1.0/distro/LICENSE new file mode 100644 index 0000000..630ba97 --- /dev/null +++ b/1.0/distro/LICENSE @@ -0,0 +1,6 @@ +gCube System - License +------------------------------------------------------------ + +The gCube/gCore software is licensed as Free Open Source software conveying to the EUPL (http://ec.europa.eu/idabc/eupl). +The software and documentation is provided by its authors/distributors "as is" and no expressed or +implied warranty is given for its use, quality or fitness for a particular case. diff --git a/1.0/distro/MAINTAINERS b/1.0/distro/MAINTAINERS new file mode 100644 index 0000000..6e1540b --- /dev/null +++ b/1.0/distro/MAINTAINERS @@ -0,0 +1 @@ +* Lucio Lelii (lucio.lelii@isti.cnr.it), CNR, Italy \ No newline at end of file diff --git a/1.0/distro/README b/1.0/distro/README new file mode 100644 index 0000000..6b65683 --- /dev/null +++ b/1.0/distro/README @@ -0,0 +1,38 @@ +The gCube System - ${name} +---------------------- + +This work has been partially supported by the following European projects: DILIGENT (FP6-2003-IST-2), D4Science (FP7-INFRA-2007-1.2.2), +D4Science-II (FP7-INFRA-2008-1.2.2), iMarine (FP7-INFRASTRUCTURES-2011-2), and EUBrazilOpenBio (FP7-ICT-2011-EU-Brazil). + +Authors +------- + +* Lucio Lelii (lucio.lelii@isti.cnr.it), CNR, Italy + +Version and Release Date +------------------------ +${version} + +Description +----------- +${description} + +Download information +-------------------- + +Source code is available from SVN: +${scm.url} + +Binaries can be downloaded from: + + +Documentation +------------- +Documentation is available on-line from the Projects Documentation Wiki: +https://gcube.wiki.gcube-system.org/gcube/index.php/.... + + +Licensing +--------- + +This software is licensed under the terms you may find in the file named "LICENSE" in this directory. diff --git a/1.0/distro/changelog.xml b/1.0/distro/changelog.xml new file mode 100644 index 0000000..ef80242 --- /dev/null +++ b/1.0/distro/changelog.xml @@ -0,0 +1,5 @@ + + + First Release + + \ No newline at end of file diff --git a/1.0/distro/descriptor.xml b/1.0/distro/descriptor.xml new file mode 100644 index 0000000..21d8c88 --- /dev/null +++ b/1.0/distro/descriptor.xml @@ -0,0 +1,42 @@ + + servicearchive + + tar.gz + + / + + + ${distroDirectory} + / + true + + README + LICENSE + INSTALL + MAINTAINERS + changelog.xml + + 755 + true + + + + + ${distroDirectory}/profile.xml + / + true + + + target/${build.finalName}.jar + /${artifactId} + + + ${distroDirectory}/svnpath.txt + /${artifactId} + true + + + \ No newline at end of file diff --git a/1.0/distro/profile.xml b/1.0/distro/profile.xml new file mode 100644 index 0000000..91c49e4 --- /dev/null +++ b/1.0/distro/profile.xml @@ -0,0 +1,26 @@ + + + + Service + + ${description} + Common + ${artifactId} + 1.0.0 + + + ${artifactId} + ${version} + + ${groupId} + ${artifactId} + ${version} + + + ${build.finalName}.jar + + + + + + diff --git a/1.0/distro/svnpath.txt b/1.0/distro/svnpath.txt new file mode 100644 index 0000000..f416f9d --- /dev/null +++ b/1.0/distro/svnpath.txt @@ -0,0 +1 @@ +${scm.url} diff --git a/1.0/pom.xml b/1.0/pom.xml new file mode 100644 index 0000000..41f6a40 --- /dev/null +++ b/1.0/pom.xml @@ -0,0 +1,105 @@ + + 4.0.0 + org.gcube.common + authorization-client + 1.0.0-SNAPSHOT + authorization service client library + + + maven-parent + org.gcube.tools + 1.0.0 + + + + distro + + + + + org.gcube.common + common-authorization + [1.0.0-SNAPSHOT,2.0.0-SNAPSHOT) + + + + org.gcube.core + common-generic-clients + [1.0.0-SNAPSHOT,2.0.0-SNAPSHOT) + + + + org.slf4j + slf4j-api + 1.7.5 + + + junit + junit + 4.11 + test + + + ch.qos.logback + logback-classic + 1.0.13 + test + + + + + + + + + + + org.apache.maven.plugins + maven-resources-plugin + 2.5 + + + copy-profile + install + + copy-resources + + + target + + + ${distroDirectory} + true + + profile.xml + + + + + + + + + + org.apache.maven.plugins + maven-assembly-plugin + + + ${distroDirectory}/descriptor.xml + + + + + servicearchive + install + + single + + + + + + + + \ No newline at end of file diff --git a/1.0/src/main/java/org/gcube/common/authorization/client/Binder.java b/1.0/src/main/java/org/gcube/common/authorization/client/Binder.java new file mode 100644 index 0000000..eea611b --- /dev/null +++ b/1.0/src/main/java/org/gcube/common/authorization/client/Binder.java @@ -0,0 +1,22 @@ +package org.gcube.common.authorization.client; + + +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBException; + +import org.gcube.common.authorization.library.AuthorizationEntry; +import org.gcube.common.authorization.library.BannedService; +import org.gcube.common.authorization.library.BannedServices; + +public class Binder { + + private static JAXBContext context ; + + public static JAXBContext getContext() throws JAXBException{ + if (context==null) + context = JAXBContext.newInstance(AuthorizationEntry.class, BannedService.class, BannedServices.class); + return context; + } + + +} diff --git a/1.0/src/main/java/org/gcube/common/authorization/client/Constants.java b/1.0/src/main/java/org/gcube/common/authorization/client/Constants.java new file mode 100644 index 0000000..27d6a2f --- /dev/null +++ b/1.0/src/main/java/org/gcube/common/authorization/client/Constants.java @@ -0,0 +1,35 @@ +package org.gcube.common.authorization.client; + +import java.util.concurrent.TimeUnit; + +import javax.xml.namespace.QName; + +import org.gcube.common.authorization.client.plugin.AuthorizationPlugin; +import org.gcube.common.authorization.client.proxy.AuthorizationProxy; +import org.gcube.common.clients.ProxyBuilder; +import org.gcube.common.clients.ProxyBuilderImpl; + +public class Constants { + + /** Service name. */ + public static final String SERVICE_NAME = "AuthorizationService"; + + /** Service class. */ + public static final String SERVICE_CLASS = "Common"; + + public static final String CONTEXT_SERVICE_NAME="authorization-service"; + + public static final int DEFAULT_TIMEOUT= (int) TimeUnit.SECONDS.toMillis(10); + + private static final String TNS = "http://gcube-system.org/"; + + public static final QName AUTHORIZATION_QNAME = new QName(TNS, "authorization-service"); + + public static final String SCOPE_HEADER_ENTRY = "gcube-scope"; + + public static final long TIME_TO_LIVE_CACHE_IN_MILLIS = (60*1000)*60; //1 hour + + public static ProxyBuilder authorizationService() { + return new ProxyBuilderImpl(new AuthorizationPlugin()); + } +} diff --git a/1.0/src/main/java/org/gcube/common/authorization/client/JaxRSEndpointReference.java b/1.0/src/main/java/org/gcube/common/authorization/client/JaxRSEndpointReference.java new file mode 100644 index 0000000..04f7faa --- /dev/null +++ b/1.0/src/main/java/org/gcube/common/authorization/client/JaxRSEndpointReference.java @@ -0,0 +1,60 @@ +package org.gcube.common.authorization.client; + +import java.io.StringReader; +import java.io.StringWriter; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.transform.stream.StreamResult; +import javax.xml.ws.EndpointReference; +import org.w3c.dom.Document; +import org.w3c.dom.NodeList; +import org.xml.sax.InputSource; + +public class JaxRSEndpointReference { + + private static final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + + private static final String addressLocalName = "Address"; + //private static final String keyLocalName = "ResourceKey"; + + String address; + //Element key; + + static { + factory.setNamespaceAware(true); + } + + public JaxRSEndpointReference(EndpointReference reference) { + this(serialise(reference)); + } + + public JaxRSEndpointReference(String reference) { + + try { + + Document document = factory.newDocumentBuilder().parse(new InputSource(new StringReader(reference))); + + NodeList addresses = document.getElementsByTagNameNS("*", addressLocalName); + + if (addresses.getLength() == 0) + throw new RuntimeException("reference does not contain an address"); + + address = addresses.item(0).getTextContent(); + + } catch (Exception e) { + throw new IllegalArgumentException("reference is not a gCore reference", e); + } + + } + + @Override + public String toString() { + return address; + } + + // helper + private static String serialise(EndpointReference reference) { + StringWriter writer = new StringWriter(); + reference.writeTo(new StreamResult(writer)); + return writer.toString(); + } +} diff --git a/1.0/src/main/java/org/gcube/common/authorization/client/Utils.java b/1.0/src/main/java/org/gcube/common/authorization/client/Utils.java new file mode 100644 index 0000000..3677c5c --- /dev/null +++ b/1.0/src/main/java/org/gcube/common/authorization/client/Utils.java @@ -0,0 +1,9 @@ +package org.gcube.common.authorization.client; + +public class Utils { + + static void notNull(String message,Object o) { + if (o==null) + throw new IllegalArgumentException(o+" cannot be null"); + } +} diff --git a/1.0/src/main/java/org/gcube/common/authorization/client/exceptions/ObjectNotFound.java b/1.0/src/main/java/org/gcube/common/authorization/client/exceptions/ObjectNotFound.java new file mode 100644 index 0000000..0d7f988 --- /dev/null +++ b/1.0/src/main/java/org/gcube/common/authorization/client/exceptions/ObjectNotFound.java @@ -0,0 +1,27 @@ +package org.gcube.common.authorization.client.exceptions; + +public class ObjectNotFound extends Exception { + + /** + * + */ + private static final long serialVersionUID = 1L; + + public ObjectNotFound() { + super(); + } + + public ObjectNotFound(String message, Throwable cause) { + super(message, cause); + } + + public ObjectNotFound(String message) { + super(message); + } + + public ObjectNotFound(Throwable cause) { + super(cause); + } + + +} diff --git a/1.0/src/main/java/org/gcube/common/authorization/client/plugin/AbstractPlugin.java b/1.0/src/main/java/org/gcube/common/authorization/client/plugin/AbstractPlugin.java new file mode 100644 index 0000000..9b4e910 --- /dev/null +++ b/1.0/src/main/java/org/gcube/common/authorization/client/plugin/AbstractPlugin.java @@ -0,0 +1,37 @@ +package org.gcube.common.authorization.client.plugin; + +import org.gcube.common.authorization.client.Constants; +import org.gcube.common.clients.Plugin; + + + +public abstract class AbstractPlugin implements Plugin { + + + public final String name; + + public AbstractPlugin(String name) { + this.name=name; + } + + @Override + public String serviceClass() { + return Constants.SERVICE_CLASS; + } + + @Override + public String serviceName() { + return Constants.SERVICE_NAME; + } + + @Override + public String name() { + return name; + } + + @Override + public String namespace() { + return ""; + } + +} \ No newline at end of file diff --git a/1.0/src/main/java/org/gcube/common/authorization/client/plugin/AuthorizationPlugin.java b/1.0/src/main/java/org/gcube/common/authorization/client/plugin/AuthorizationPlugin.java new file mode 100644 index 0000000..0c5d98d --- /dev/null +++ b/1.0/src/main/java/org/gcube/common/authorization/client/plugin/AuthorizationPlugin.java @@ -0,0 +1,35 @@ +package org.gcube.common.authorization.client.plugin; + + +import javax.xml.ws.EndpointReference; + +import org.gcube.common.authorization.client.JaxRSEndpointReference; +import org.gcube.common.authorization.client.proxy.AuthorizationProxy; +import org.gcube.common.authorization.client.proxy.DefaultAuthorizationProxy; +import org.gcube.common.clients.config.ProxyConfig; +import org.gcube.common.clients.delegates.ProxyDelegate; + +public class AuthorizationPlugin extends AbstractPlugin{ + + public AuthorizationPlugin() { + super("authorization-service/gcube/service"); + } + + @Override + public Exception convert(Exception fault, ProxyConfig config) { + return fault; + } + + @Override + public String resolve(EndpointReference address, ProxyConfig config) + throws Exception { + return new JaxRSEndpointReference(address).toString(); + + } + + @Override + public AuthorizationProxy newProxy(ProxyDelegate delegate) { + return new DefaultAuthorizationProxy(delegate); + } + +} diff --git a/1.0/src/main/java/org/gcube/common/authorization/client/proxy/AuthorizationEntryCache.java b/1.0/src/main/java/org/gcube/common/authorization/client/proxy/AuthorizationEntryCache.java new file mode 100644 index 0000000..7adb697 --- /dev/null +++ b/1.0/src/main/java/org/gcube/common/authorization/client/proxy/AuthorizationEntryCache.java @@ -0,0 +1,23 @@ +package org.gcube.common.authorization.client.proxy; + +import org.gcube.common.authorization.client.Constants; +import org.gcube.common.authorization.library.AuthorizationEntry; + +public class AuthorizationEntryCache { + + private AuthorizationEntry entry; + private long creationDate; + + public AuthorizationEntryCache(AuthorizationEntry entry) { + super(); + this.entry = entry; + this.creationDate = System.currentTimeMillis(); + } + public AuthorizationEntry getEntry() { + return entry; + } + + public boolean isValid(){ + return (System.currentTimeMillis()-Constants.TIME_TO_LIVE_CACHE_IN_MILLIS) roles); + + AuthorizationEntry get(String token) throws ObjectNotFound; + + BannedService deny(String userName, String serviceClass, String serviceName); + + void allow(String userName, String serviceClass, String serviceName); + + List getBannedServices(String userName); +} diff --git a/1.0/src/main/java/org/gcube/common/authorization/client/proxy/DefaultAuthorizationProxy.java b/1.0/src/main/java/org/gcube/common/authorization/client/proxy/DefaultAuthorizationProxy.java new file mode 100644 index 0000000..e247d43 --- /dev/null +++ b/1.0/src/main/java/org/gcube/common/authorization/client/proxy/DefaultAuthorizationProxy.java @@ -0,0 +1,180 @@ +package org.gcube.common.authorization.client.proxy; + +import static org.gcube.common.clients.exceptions.FaultDSL.again; + +import java.io.BufferedReader; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.net.HttpURLConnection; +import java.net.URL; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.gcube.common.authorization.client.Binder; +import org.gcube.common.authorization.client.Constants; +import org.gcube.common.authorization.client.exceptions.ObjectNotFound; +import org.gcube.common.authorization.library.AuthorizationEntry; +import org.gcube.common.authorization.library.BannedService; +import org.gcube.common.authorization.library.BannedServices; +import org.gcube.common.clients.Call; +import org.gcube.common.clients.delegates.ProxyDelegate; +import org.gcube.common.clients.stubs.jaxws.JAXWSUtils.Empty; +import org.gcube.common.scope.api.ScopeProvider; + +public class DefaultAuthorizationProxy implements AuthorizationProxy { + + private final ProxyDelegate delegate; + + public DefaultAuthorizationProxy(ProxyDelegate config){ + this.delegate = config; + } + + private static Map cache = new HashMap(); + + @Override + public String generate(final String userName, final List roles) { + Call call = new Call() { + + @Override + public String call(String endpoint) throws Exception { + StringBuilder rolesQueryString = new StringBuilder(); + for (String role: roles) + rolesQueryString.append(role).append(","); + rolesQueryString.deleteCharAt(rolesQueryString.lastIndexOf(",")); + String callUrl = endpoint+"/generate/"+userName+"?roles="+rolesQueryString.toString(); + URL url = new URL(callUrl); + HttpURLConnection connection = makeRequest(url, "POST"); + if (connection.getResponseCode()!=200) throw new Exception("error contacting authorization service"); + try(BufferedReader reader = new BufferedReader(new InputStreamReader((InputStream)connection.getContent()));){ + StringBuilder result = new StringBuilder(); + String line; + while((line = reader.readLine()) != null) + result.append(line); + return result.toString(); + } + } + }; + try { + return delegate.make(call); + } catch (Exception e) { + throw again(e).asServiceException(); + } + } + + @Override + public AuthorizationEntry get(final String token) throws ObjectNotFound{ + Call call = new Call() { + + @Override + public AuthorizationEntry call(String endpoint) throws Exception { + + URL url = new URL(endpoint+"/retrieve/"+token); + HttpURLConnection connection = makeRequest(url, "GET"); + if (connection.getResponseCode()==404) throw new ObjectNotFound("token "+token+" not found"); + if (connection.getResponseCode()!=200) throw new Exception("error contacting authorization service"); + if (connection.getContentLengthLong()<=0) return null; + + try(InputStream stream = (InputStream)connection.getContent();){ + AuthorizationEntry entry = (AuthorizationEntry)Binder.getContext().createUnmarshaller().unmarshal(stream); + cache.put(token, new AuthorizationEntryCache(entry)); + return entry; + } + + } + }; + if (cache.containsKey(token) && cache.get(token).isValid()) + return cache.get(token).getEntry(); + try { + return delegate.make(call); + } catch (ObjectNotFound e) { + throw e; + } catch (Exception e) { + throw again(e).asServiceException(); + } + } + + @Override + public BannedService deny(final String userName, final String serviceClass, final String serviceName) { + Call call = new Call() { + @Override + public BannedService call(String endpoint) throws Exception { + URL url = new URL(endpoint+"/deny/"+userName+"/"+serviceClass+"/"+serviceName); + HttpURLConnection connection = makeRequest(url, "POST"); + + if (connection.getResponseCode()!=200 && connection.getResponseCode()!=200) throw new Exception("error contacting authorization service"); + if (connection.getContentLengthLong()<=0) return null; + + try(InputStream stream = (InputStream)connection.getContent();){ + BannedService service = (BannedService)Binder.getContext().createUnmarshaller().unmarshal(stream); + return service; + } + } + }; + + try { + return delegate.make(call); + } catch (Exception e) { + throw again(e).asServiceException(); + } + } + + @Override + public void allow(final String userName, final String serviceClass, final String serviceName) { + Call call = new Call() { + + @Override + public Empty call(String endpoint) throws Exception { + URL url = new URL(endpoint+"/deny/"+userName+"/"+serviceClass+"/"+serviceName); + HttpURLConnection connection = makeRequest(url, "DELETE"); + if (!(connection.getResponseCode()>=200 && connection.getResponseCode()<=206)) throw new Exception("error contacting authorization service"); + return new Empty(); + + } + }; + + try { + delegate.make(call); + } catch (Exception e) { + throw again(e).asServiceException(); + } + } + + @Override + public List getBannedServices(final String userName) { + Call> call = new Call>() { + + @Override + public List call(String endpoint) throws Exception { + + URL url = new URL(endpoint+"/deny/"+userName); + + HttpURLConnection connection = makeRequest(url, "GET"); + if (connection.getResponseCode()!=200) throw new Exception("error contacting authorization service"); + if (connection.getContentLengthLong()<=0) return Collections.emptyList(); + + try(InputStream stream = (InputStream)connection.getContent();){ + BannedServices services = (BannedServices)Binder.getContext().createUnmarshaller().unmarshal(stream); + if (services.get()==null) return Collections.emptyList(); + else return services.get(); + } + + } + }; + + try { + return delegate.make(call); + } catch (Exception e) { + throw again(e).asServiceException(); + } + } + + + private HttpURLConnection makeRequest(URL url, String method) throws Exception{ + HttpURLConnection connection = (HttpURLConnection)url.openConnection(); + connection.setRequestProperty(Constants.SCOPE_HEADER_ENTRY, ScopeProvider.instance.get()); + connection.setRequestMethod(method); + return connection; + } +} diff --git a/1.0/src/test/java/org/gcube/common/authorizationservice/cl/CallTest.java b/1.0/src/test/java/org/gcube/common/authorizationservice/cl/CallTest.java new file mode 100644 index 0000000..afee75c --- /dev/null +++ b/1.0/src/test/java/org/gcube/common/authorizationservice/cl/CallTest.java @@ -0,0 +1,60 @@ +package org.gcube.common.authorizationservice.cl; + +import static org.gcube.common.authorization.client.Constants.authorizationService; + +import java.util.Arrays; +import java.util.List; + +import org.gcube.common.authorization.client.exceptions.ObjectNotFound; +import org.gcube.common.authorization.library.BannedService; +import org.gcube.common.scope.api.ScopeProvider; +import org.junit.Test; +public class CallTest { + + + @Test + public void call(){ + ScopeProvider.instance.set("/gcube/devsec"); + try{ + System.out.println(authorizationService().build().get("a00affeb-0b75-4152-a134-e5c432a9a70a")); + }catch(ObjectNotFound onf){ + onf.printStackTrace(); + } + } + + @Test + public void requestToken(){ + + ScopeProvider.instance.set("/gcube/devNext/NextNext"); + String token = authorizationService().build().generate("fabio.sinibaldi", Arrays.asList("User")); + System.out.println("token is: "+token); + + } + + @Test + public void denyService(){ + + ScopeProvider.instance.set("/gcube/devsec"); + authorizationService().build().deny("giancarlo.panichi", "WPS", "DataMiner"); + + } + + @Test + public void allowService(){ + + ScopeProvider.instance.set("/gcube/devsec"); + authorizationService().build().allow("lucio.lelii", "Test", "AuthorizationTest"); + + } + + @Test + public void getBannedServices(){ + + ScopeProvider.instance.set("/gcube/devsec"); + List bannedServices = authorizationService().build().getBannedServices("lucio.lelii"); + for (BannedService banService : bannedServices) + System.out.println(banService); + + } + +}