commit fd513d1592f87865e8d201de676bc1389171646e Author: Lucio Lelii Date: Mon Oct 3 14:22:42 2016 +0000 branch for release 4.1 git-svn-id: https://svn.d4science-ii.research-infrastructures.eu/gcube/branches/common/authorization-service/2.0@132472 82a268e6-3cf1-43bd-a215-b396298e98cf diff --git a/.classpath b/.classpath new file mode 100644 index 0000000..e43402f --- /dev/null +++ b/.classpath @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.project b/.project new file mode 100644 index 0000000..34bcc98 --- /dev/null +++ b/.project @@ -0,0 +1,29 @@ + + + authorization-service + + + + + + org.eclipse.wst.common.project.facet.core.builder + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.m2e.core.maven2Builder + + + + + + org.eclipse.jdt.core.javanature + org.eclipse.m2e.core.maven2Nature + org.eclipse.wst.common.project.facet.core.nature + + diff --git a/.settings/org.eclipse.core.resources.prefs b/.settings/org.eclipse.core.resources.prefs new file mode 100644 index 0000000..29abf99 --- /dev/null +++ b/.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/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..ec4300d --- /dev/null +++ b/.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/.settings/org.eclipse.m2e.core.prefs b/.settings/org.eclipse.m2e.core.prefs new file mode 100644 index 0000000..f897a7f --- /dev/null +++ b/.settings/org.eclipse.m2e.core.prefs @@ -0,0 +1,4 @@ +activeProfiles= +eclipse.preferences.version=1 +resolveWorkspaceProjects=true +version=1 diff --git a/distro/LICENSE b/distro/LICENSE new file mode 100644 index 0000000..3695e26 --- /dev/null +++ b/distro/LICENSE @@ -0,0 +1 @@ +${gcube.license} diff --git a/distro/README b/distro/README new file mode 100644 index 0000000..4f0f224 --- /dev/null +++ b/distro/README @@ -0,0 +1,62 @@ +The gCube System - ${name} +-------------------------------------------------- + +${description} + + +${gcube.description} + +${gcube.funding} + + +Version +-------------------------------------------------- + +${version} (${buildDate}) + +Please see the file named "changelog.xml" in this directory for the release notes. + + +Authors +-------------------------------------------------- + +* Lucio Lelii (lucio.lelii-AT-isti.cnr.it), CNR, Italy + +Maintainers +-------------------------------------------------- + +* Lucio Lelii (lucio.lelii-AT-isti.cnr.it), CNR, Italy + +Download information +-------------------------------------------------- + +Source code is available from SVN: + ${scm.url} + +Binaries can be downloaded from the gCube website: + ${gcube.website} + + +Installation +-------------------------------------------------- + +Installation documentation is available on-line in the gCube Wiki: + ${gcube.wikiRoot} + +Documentation +-------------------------------------------------- + +Documentation is available on-line in the gCube Wiki: + ${gcube.wikiRoot} + +Support +-------------------------------------------------- + +Bugs and support requests can be reported in the gCube issue tracking tool: + ${gcube.issueTracking} + + +Licensing +-------------------------------------------------- + +This software is licensed under the terms you may find in the file named "LICENSE" in this directory. diff --git a/distro/changelog.xml b/distro/changelog.xml new file mode 100644 index 0000000..bfa0593 --- /dev/null +++ b/distro/changelog.xml @@ -0,0 +1,8 @@ + + + First Release + + + moved auth to new auth2 model + + \ No newline at end of file diff --git a/distro/descriptor.xml b/distro/descriptor.xml new file mode 100644 index 0000000..5ba272a --- /dev/null +++ b/distro/descriptor.xml @@ -0,0 +1,35 @@ + + servicearchive + + tar.gz + + / + + + ${distroDirectory} + / + true + + README + LICENSE + changelog.xml + + 755 + true + + + + + ${distroDirectory}/profile.xml + / + true + + + target/${build.finalName}.war + /${artifactId} + + + diff --git a/distro/profile.xml b/distro/profile.xml new file mode 100644 index 0000000..91c49e4 --- /dev/null +++ b/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/pom.xml b/pom.xml new file mode 100644 index 0000000..7a5067e --- /dev/null +++ b/pom.xml @@ -0,0 +1,209 @@ + + 4.0.0 + + + maven-parent + org.gcube.tools + 1.0.0 + + + org.gcube.common + authorization-service + 2.0.0-SNAPSHOT + authorization service + + war + + + distro + + + + + + org.gcube.common + common-authorization + [2.0.0-SNAPSHOT, 3.0.0-SNAPSHOT) + + + + org.gcube.core + common-encryption + [1.0.0-SNAPSHOT, 2.0.0-SNAPSHOT) + + + + org.gcube.core + common-scope-maps + [1.0.0-SNAPSHOT,2.0.0-SNAPSHOT) + + + + org.gcube.core + common-scope + [1.0.0-SNAPSHOT,2.0.0-SNAPSHOT) + + + + org.gcube.core + common-encryption + [1.0.0-SNAPSHOT, 2.0.0-SNAPSHOT) + + + + + javax.ws.rs + javax.ws.rs-api + 2.0 + + + org.glassfish.jersey.containers + jersey-container-servlet + 2.13 + + + org.glassfish.jersey.containers.glassfish + jersey-gf-cdi + 2.13 + + + + javax.transaction + javax.transaction-api + 1.2 + + + javax.servlet + javax.servlet-api + 3.0.1 + provided + + + + postgresql + postgresql + 9.1-901.jdbc4 + runtime + + + + + javax.enterprise + cdi-api + 1.1 + + + org.jboss.weld.servlet + weld-servlet + 2.2.4.Final + + + org.jboss + jandex + 1.2.2.Final + + + + + + org.projectlombok + lombok + 0.11.6 + + + + eclipselink + org.eclipse.persistence + 2.5.1 + + + + ch.qos.logback + logback-classic + 1.0.13 + + + + org.glassfish.jersey.test-framework.providers + jersey-test-framework-provider-simple + 2.17 + test + + + + org.apache.derby + derby + 10.8.2.2 + test + + + org.apache.derby + derbyclient + 10.8.2.2 + test + + + + com.googlecode.jeeunit + jeeunit + 1.0.0 + test + + + + com.google.code.gson + gson + 2.7 + test + + + org.gcube.common + couchdb-connector + 2.0.0-SNAPSHOT + test + + + + + + ${artifactId} + + + maven-compiler-plugin + 2.3.2 + + 1.7 + 1.7 + + + + org.apache.maven.plugins + maven-war-plugin + 2.4 + + authorization-service + false + + + + org.apache.maven.plugins + maven-assembly-plugin + + + ${distroDirectory}/descriptor.xml + + + + + servicearchive + install + + single + + + + + + + \ No newline at end of file diff --git a/src/main/java/org/gcube/common/authorizationservice/ApiKeyManager.java b/src/main/java/org/gcube/common/authorizationservice/ApiKeyManager.java new file mode 100644 index 0000000..405acf4 --- /dev/null +++ b/src/main/java/org/gcube/common/authorizationservice/ApiKeyManager.java @@ -0,0 +1,117 @@ +package org.gcube.common.authorizationservice; + +import java.util.UUID; + +import javax.inject.Inject; +import javax.servlet.http.HttpServletRequest; +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + +import lombok.extern.slf4j.Slf4j; + +import org.gcube.common.authorization.library.AuthorizationEntry; +import org.gcube.common.authorization.library.QualifiersList; +import org.gcube.common.authorizationservice.filters.AuthorizedCallFilter; +import org.gcube.common.authorizationservice.util.Constants; +import org.gcube.common.authorizationservice.util.TokenPersistence; + +@Path("apikey") +@Slf4j +public class ApiKeyManager { + + @Inject + TokenPersistence persistence; + + + /** + * + * Generates an api key. + * + * @param serviceName the name of the client that will use this apikey + * @return the generated api key + */ + @PUT + @Consumes(MediaType.APPLICATION_XML) + public String generateApiKey(@QueryParam(value="qualifier")String qualifier, @Context HttpServletRequest req) { + try{ + + AuthorizationEntry info = (AuthorizationEntry)req.getAttribute(AuthorizedCallFilter.AUTH_ATTRIBUTE); + + if (qualifier==null || qualifier.isEmpty() || qualifier.equals(Constants.DEFAULT_TOKEN_QUALIFIER)) + throw new IllegalArgumentException(); + + log.info("generator called with user {} in context {} ",info.getClientInfo(), info.getContext()); + + if (info.getClientInfo().getId().split(":").length>1) throw new Exception("invalid user id: "+info.getClientInfo()); + + String token = persistence.getExistingToken(info.getClientInfo().getId(), info.getContext(), qualifier); + + if (token==null){ + token = UUID.randomUUID().toString(); + persistence.saveAuthorizationEntry(token, info.getContext(), info.getClientInfo(), qualifier, info.getClientInfo().getId()); + } + + return token; + }catch(Exception e){ + log.error("error generating apikey ",e); + throw new WebApplicationException(Response.status(Response.Status.BAD_REQUEST) + .entity("Error Generating ApiKey: "+e.getMessage()).type(MediaType.TEXT_PLAIN).build()); + } + } + + /** + * + * retrieves the AuthorzationEntry connected to the specified token + * + * @param token + * @return the authorization entry + */ + @GET + @Produces(MediaType.APPLICATION_XML) + public QualifiersList retrieveApiKeys(@Context HttpServletRequest req) { + log.info("calling getApiKey"); + try{ + AuthorizationEntry info = (AuthorizationEntry)req.getAttribute(AuthorizedCallFilter.AUTH_ATTRIBUTE); + + return new QualifiersList(persistence.getExistingApiKeys(info.getClientInfo().getId(), info.getContext())); + + }catch(Exception e){ + log.error("error retrieving apikey",e); + } + return null; + } + + /** + * + * removes an api key. + * + * @param the key to remove + * @return + */ + @Path("{key}") + @DELETE + public void removeApiKey(@PathParam(value="key")String key, @Context HttpServletRequest req) { + try{ + + //TODO + + + }catch(Exception e){ + log.error("error generating apikey ",e); + throw new WebApplicationException(Response.status(Response.Status.BAD_REQUEST) + .entity("Error Generating ApiKey: "+e.getMessage()).type(MediaType.TEXT_PLAIN).build()); + } + } + + +} diff --git a/src/main/java/org/gcube/common/authorizationservice/AuthorizationService.java b/src/main/java/org/gcube/common/authorizationservice/AuthorizationService.java new file mode 100644 index 0000000..516b0b3 --- /dev/null +++ b/src/main/java/org/gcube/common/authorizationservice/AuthorizationService.java @@ -0,0 +1,18 @@ +package org.gcube.common.authorizationservice; + +import javax.ws.rs.ApplicationPath; + +import org.gcube.common.authorizationservice.configuration.AuthorizationConfiguration; +import org.glassfish.jersey.server.ResourceConfig; + +@ApplicationPath("/gcube/service/") +public class AuthorizationService extends ResourceConfig { + + public static AuthorizationConfiguration configuration; + + public AuthorizationService(){ + packages("org.gcube.common.authorizationservice"); + + } + +} \ No newline at end of file diff --git a/src/main/java/org/gcube/common/authorizationservice/KeyRetriever.java b/src/main/java/org/gcube/common/authorizationservice/KeyRetriever.java new file mode 100644 index 0000000..b10a67d --- /dev/null +++ b/src/main/java/org/gcube/common/authorizationservice/KeyRetriever.java @@ -0,0 +1,74 @@ +package org.gcube.common.authorizationservice; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.security.InvalidKeyException; + +import javax.servlet.http.HttpServletRequest; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; +import javax.ws.rs.core.StreamingOutput; + +import lombok.extern.slf4j.Slf4j; + +import org.gcube.common.authorization.library.AuthorizationEntry; +import org.gcube.common.authorization.library.provider.ContainerInfo; +import org.gcube.common.authorizationservice.filters.AuthorizedCallFilter; +import org.gcube.common.scope.impl.ScopeBean; +import org.gcube.common.scope.impl.ScopeBean.Type; + +@Path("symmKey") +@Slf4j +public class KeyRetriever { + + @GET + @Produces(MediaType.APPLICATION_OCTET_STREAM) + public Response getKey(@Context HttpServletRequest req) throws Exception { + final AuthorizationEntry info = (AuthorizationEntry)req.getAttribute(AuthorizedCallFilter.AUTH_ATTRIBUTE); + if (info.getClientInfo() instanceof ContainerInfo){ + final String keyFileName =getKeyFileName(info.getContext()); + StreamingOutput so = new StreamingOutput() { + public void write(OutputStream output) throws IOException, WebApplicationException { + try{ + + try(InputStream is =KeyRetriever.class.getResourceAsStream("/"+keyFileName)){ + byte[] buffer = new byte[8192]; + int read = -1; + while ((read = is.read(buffer))!=-1){ + output.write(buffer, 0, read); + } + } + }catch(Exception e){ + log.error("error retrieving symm key", e); + throw new WebApplicationException(e, Status.INTERNAL_SERVER_ERROR); + } + } + }; + return Response.ok(so).header("content-disposition","attachment; filename = "+keyFileName) + .header("resource-name", keyFileName).build(); + } else return Response.status(Status.UNAUTHORIZED).build(); + } + + protected static String getKeyFileName(String context) throws InvalidKeyException{ + String keyFile=null; + if(context!=null){ + ScopeBean bean = new ScopeBean(context); + if(bean.is(Type.VRE)) + bean = bean.enclosingScope(); + String name = bean.name(); + //build keyfile name with name + keyFile=name+".gcubekey"; + }else{ + throw new InvalidKeyException("invalid key for context: "+context); + } + return keyFile; + } + +} diff --git a/src/main/java/org/gcube/common/authorizationservice/PolicyManager.java b/src/main/java/org/gcube/common/authorizationservice/PolicyManager.java new file mode 100644 index 0000000..77b68f2 --- /dev/null +++ b/src/main/java/org/gcube/common/authorizationservice/PolicyManager.java @@ -0,0 +1,75 @@ +package org.gcube.common.authorizationservice; + +import javax.inject.Inject; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Null; +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + +import org.gcube.common.authorization.library.Policies; +import org.gcube.common.authorizationservice.util.TokenPersistence; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +@Path("policyManager") +public class PolicyManager { + + private static Logger log = LoggerFactory.getLogger(PolicyManager.class); + + @Inject + TokenPersistence tokenPersistence; + + @POST + @Consumes(MediaType.APPLICATION_XML) + public Response setPolices(Policies policies) { + try{ + log.info("adding policies: {}", policies.getPolicies()); + tokenPersistence.addPolicies(policies.getPolicies()); + }catch(Exception e){ + log.error("error adding policies",e); + throw new WebApplicationException(Response.status(Response.Status.BAD_REQUEST) + .entity("Error adding policies: "+e.getMessage()).type(MediaType.TEXT_PLAIN).build()); + } + return Response.ok().build(); + } + + @DELETE + @Consumes(MediaType.APPLICATION_XML) + @Path("{policy_id}") + public Response remove(@Null @PathParam("policy_id") long policyId) { + try{ + log.info("removing policy with id {}", policyId); + tokenPersistence.removePolicy(policyId); + }catch(Exception e){ + log.error("error removing policies", e); + throw new WebApplicationException(Response.status(Response.Status.BAD_REQUEST) + .entity("Error removing policies: "+e.getMessage()).type(MediaType.TEXT_PLAIN).build()); + } + return Response.ok().build(); + } + + @GET + @Produces(MediaType.APPLICATION_XML) + public Policies getPoliciesPerContext(@NotNull @QueryParam("context") String context) { + try{ + log.info("retrieving polices in context {}", context); + return new Policies(tokenPersistence.getPolices(context)); + }catch(Exception e){ + log.error("error retrieving policies per context {}", context, e); + throw new WebApplicationException(Response.status(Response.Status.BAD_REQUEST) + .entity("Error retrieving policies: "+e.getMessage()).type(MediaType.TEXT_PLAIN).build()); + } + } + + + +} diff --git a/src/main/java/org/gcube/common/authorizationservice/TokenManager.java b/src/main/java/org/gcube/common/authorizationservice/TokenManager.java new file mode 100644 index 0000000..8b6d09b --- /dev/null +++ b/src/main/java/org/gcube/common/authorizationservice/TokenManager.java @@ -0,0 +1,235 @@ +package org.gcube.common.authorizationservice; + +import java.util.UUID; + +import javax.inject.Inject; +import javax.servlet.http.HttpServletRequest; +import javax.validation.constraints.NotNull; +import javax.ws.rs.Consumes; +import javax.ws.rs.GET; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + +import lombok.extern.slf4j.Slf4j; + +import org.gcube.common.authorization.library.AuthorizationEntry; +import org.gcube.common.authorization.library.provider.ContainerInfo; +import org.gcube.common.authorization.library.provider.ExternalServiceInfo; +import org.gcube.common.authorization.library.provider.ServiceInfo; +import org.gcube.common.authorization.library.provider.UserInfo; +import org.gcube.common.authorizationservice.filters.AuthorizedCallFilter; +import org.gcube.common.authorizationservice.util.Constants; +import org.gcube.common.authorizationservice.util.TokenPersistence; + +@Path("token") +@Slf4j +public class TokenManager { + + @Inject + TokenPersistence persistence; + + + /** + * + * retrieves the AuthorzationEntry connected to the specified token + * + * @param token + * @return the authorization entry + */ + @GET + @Path("{token}") + @Produces(MediaType.APPLICATION_XML) + public AuthorizationEntry retrieveToken(@NotNull @PathParam("token") String token ) { + + log.info("token retreiver called with token {}",token); + + AuthorizationEntry info = persistence.getAuthorizationEntry(token); + + log.info("info retrieved {}",info); + + if (info == null){ + log.error("token {} not found ", token); + throw new WebApplicationException(Response.status(Response.Status.NOT_FOUND) + .entity("token "+token+" not found").type(MediaType.TEXT_PLAIN).build()); + } + + //TODO: re-add it with common-scope 2.0 + /* + try{ + ServiceMap map = .instance.getMap(info.getContext()); + info.setMap(map); + }catch(Exception e){ + log.error("error retrieving map for {}", info.getContext(), e); + throw new WebApplicationException(Response.status(Response.Status.INTERNAL_SERVER_ERROR) + .entity("Error retrieving map").type(MediaType.TEXT_PLAIN).build()); + }*/ + + log.debug("returning info {}", info); + return info; + + } + + /** + * + * Generates a token for a user (saving the passed roles) if it doesn't exist yet. + * + * @param userName + * @param roles + * @return the generated token or the token related to the user (if it was already created) + */ + @Path("user") + @PUT + @Consumes(MediaType.APPLICATION_XML) + public String generateUserToken(UserInfo clientId, + @NotNull @QueryParam("context") String context) { + + try{ + + log.info("generator called with user {} in context {} ",clientId, context); + + if (clientId.getId().split(":").length>1) throw new Exception("invalid user id: "+clientId.getId()); + + String token = persistence.getExistingToken(clientId.getId(), context, Constants.DEFAULT_TOKEN_QUALIFIER); + + if (token==null){ + token = UUID.randomUUID().toString(); + persistence.saveAuthorizationEntry(token, context, clientId , Constants.DEFAULT_TOKEN_QUALIFIER, null); + } + + return token; + }catch(Exception e){ + log.error("error generating token ",e); + throw new WebApplicationException(Response.status(Response.Status.BAD_REQUEST) + .entity("Error Generating Token: "+e.getMessage()).type(MediaType.TEXT_PLAIN).build()); + } + } + + /** + * + * Generates a token for a service if it doesn't exist yet. + * + * @param userName + * @param roles + * @return the generated token or the token related to the user (if it was already created) + */ + @Path("service") + @PUT + @Consumes(MediaType.APPLICATION_XML) + public String generateServiceToken(ServiceInfo serviceInfo, + @Context HttpServletRequest req) { + try{ + AuthorizationEntry authInfo = (AuthorizationEntry)req.getAttribute(AuthorizedCallFilter.AUTH_ATTRIBUTE); + log.info("generator called with service {} in context {} ",serviceInfo.getId(), authInfo.getContext()); + return generateTokenForServiceInfo(serviceInfo, authInfo); + }catch(Exception e){ + log.error("error generating token ",e); + throw new WebApplicationException(Response.status(Response.Status.BAD_REQUEST) + .entity("Error Generating Token: "+e.getMessage()).type(MediaType.TEXT_PLAIN).build()); + } + } + + + + + /** + * + * Generates a token for an external service if it doesn't exist yet. + * + * @param externalServiceInfo + * @return the generated token or the token related to the external service (if it was already created) + */ + @Path("external") + @PUT + @Consumes(MediaType.APPLICATION_XML) + public String generateExternalServiceToken(ExternalServiceInfo externalService, @Context HttpServletRequest req) { + try{ + AuthorizationEntry info = (AuthorizationEntry)req.getAttribute(AuthorizedCallFilter.AUTH_ATTRIBUTE); + log.info("generator called for external service {} in context {} ",externalService.getId(), info.getContext()); + + if (externalService.getId().split(":").length>1) throw new Exception("invalid external service id: "+externalService.getId()); + + String token = persistence.getExistingToken(externalService.getId(), info.getContext(), Constants.DEFAULT_TOKEN_QUALIFIER); + + if (token==null){ + token= UUID.randomUUID().toString(); + persistence.saveAuthorizationEntry(token, info.getContext(), externalService, Constants.DEFAULT_TOKEN_QUALIFIER, null); + } + + return token; + }catch(Exception e){ + log.error("error generating token ",e); + throw new WebApplicationException(Response.status(Response.Status.BAD_REQUEST) + .entity("Error Generating Token: "+e.getMessage()).type(MediaType.TEXT_PLAIN).build()); + } + } + + @Path("node") + @PUT + @Consumes(MediaType.APPLICATION_XML) + public String generateContainerToken(@NotNull ContainerInfo containerInfo, @QueryParam("context") String context, + @Context HttpServletRequest req) { + try{ + + AuthorizationEntry info = (AuthorizationEntry)req.getAttribute(AuthorizedCallFilter.AUTH_ATTRIBUTE); + + if (context!=null) + return generateTokenForContainerInfo(containerInfo, context); + else if (info!=null){ + log.info("generator called for node {} in context {} ",containerInfo.getId(), info.getContext()); + return generateTokenForContainerInfo(containerInfo, info); + } + + throw new Exception("error trying to activate node (token and context are empty)"); + }catch(Exception e){ + log.error("error generating token ",e); + throw new WebApplicationException(Response.status(Response.Status.BAD_REQUEST) + .entity("Error Generating Token: "+e.getMessage()).type(MediaType.TEXT_PLAIN).build()); + } + } + + private String generateTokenForContainerInfo(ContainerInfo containerInfo,String context) throws Exception{ + if (containerInfo.getId().split(":").length!=2) throw new Exception("invalid container id: "+containerInfo.getId()); + + String token = persistence.getExistingToken(containerInfo.getId(), context, Constants.DEFAULT_TOKEN_QUALIFIER); + + if( token ==null){ + token = UUID.randomUUID().toString();; + persistence.saveAuthorizationEntry(token, context, containerInfo, Constants.DEFAULT_TOKEN_QUALIFIER, null); + + } + return token; + } + + private String generateTokenForContainerInfo(ContainerInfo containerInfo, AuthorizationEntry authInfo) throws Exception{ + if (containerInfo.getId().split(":").length!=2) throw new Exception("invalid container id: "+containerInfo.getId()); + + String token = persistence.getExistingToken(containerInfo.getId(),authInfo.getContext(), Constants.DEFAULT_TOKEN_QUALIFIER); + + if( token ==null){ + token = UUID.randomUUID().toString();; + persistence.saveAuthorizationEntry(token, authInfo.getContext(), containerInfo, Constants.DEFAULT_TOKEN_QUALIFIER, authInfo.getClientInfo().getId() ); + + } + return token; + } + + private String generateTokenForServiceInfo(ServiceInfo serviceInfo, AuthorizationEntry authInfo) throws Exception{ + if (serviceInfo.getId().split(":").length!=3) throw new Exception("invalid service id: "+serviceInfo.getId()); + + String token = persistence.getExistingToken(serviceInfo.getId(), authInfo.getContext(), Constants.DEFAULT_TOKEN_QUALIFIER); + + if( token ==null){ + token = UUID.randomUUID().toString();; + persistence.saveAuthorizationEntry(token, authInfo.getContext(), serviceInfo, Constants.DEFAULT_TOKEN_QUALIFIER, authInfo.getClientInfo().getId() ); + } + return token; + } + +} diff --git a/src/main/java/org/gcube/common/authorizationservice/configuration/AllowedEntity.java b/src/main/java/org/gcube/common/authorizationservice/configuration/AllowedEntity.java new file mode 100644 index 0000000..e71b057 --- /dev/null +++ b/src/main/java/org/gcube/common/authorizationservice/configuration/AllowedEntity.java @@ -0,0 +1,71 @@ +package org.gcube.common.authorizationservice.configuration; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlRootElement; + +@XmlRootElement(name="Entity") +@XmlAccessorType(XmlAccessType.FIELD) +public class AllowedEntity { + + public enum EntityType { + IP, ROLE, USER + } + + @XmlAttribute + private EntityType type; + + @XmlAttribute + private String value; + + protected AllowedEntity(){} + + public AllowedEntity(EntityType type, String value) { + super(); + this.type = type; + this.value = value; + } + + public EntityType getType() { + return type; + } + + public String getValue() { + return value; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((type == null) ? 0 : type.hashCode()); + result = prime * result + ((value == null) ? 0 : value.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + AllowedEntity other = (AllowedEntity) obj; + if (type != other.type) + return false; + if (value == null) { + if (other.value != null) + return false; + } else if (!value.equals(other.value)) + return false; + return true; + } + + @Override + public String toString() { + return "AllowedEntity [type=" + type + ", value=" + value + "]"; + } + +} diff --git a/src/main/java/org/gcube/common/authorizationservice/configuration/AuthorizationConfiguration.java b/src/main/java/org/gcube/common/authorizationservice/configuration/AuthorizationConfiguration.java new file mode 100644 index 0000000..a2e75d6 --- /dev/null +++ b/src/main/java/org/gcube/common/authorizationservice/configuration/AuthorizationConfiguration.java @@ -0,0 +1,88 @@ +package org.gcube.common.authorizationservice.configuration; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +@XmlRootElement(name="Configuration") +@XmlAccessorType(XmlAccessType.FIELD) +public class AuthorizationConfiguration { + + @XmlElement(name="Rule") + private List authorizationRules = new ArrayList(); + + @XmlElement(name="AllowedContainerIp") + private List allowedContainerIps = new ArrayList(); + + protected AuthorizationConfiguration(){} + + public List getAuthorizationRules() { + return Collections.unmodifiableList(authorizationRules); + } + + protected void setAuthorizationRules(List rules) { + this.authorizationRules = rules; + } + + public List getAllowedContainerIps() { + return allowedContainerIps; + } + + protected void setAllowedContainerIps( + List allowedContainerIps) { + this.allowedContainerIps = allowedContainerIps; + } + + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime + * result + + ((allowedContainerIps == null) ? 0 : allowedContainerIps + .hashCode()); + result = prime + * result + + ((authorizationRules == null) ? 0 : authorizationRules + .hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + AuthorizationConfiguration other = (AuthorizationConfiguration) obj; + if (allowedContainerIps == null) { + if (other.allowedContainerIps != null) + return false; + } else if (!allowedContainerIps.equals(other.allowedContainerIps)) + return false; + if (authorizationRules == null) { + if (other.authorizationRules != null) + return false; + } else if (!authorizationRules.equals(other.authorizationRules)) + return false; + return true; + } + + @Override + public String toString() { + return "AuthorizationConfiguration [authorizationRules=" + + authorizationRules + ", allowedContainerIps=" + + allowedContainerIps + "]"; + } + + + +} diff --git a/src/main/java/org/gcube/common/authorizationservice/configuration/AuthorizationRule.java b/src/main/java/org/gcube/common/authorizationservice/configuration/AuthorizationRule.java new file mode 100644 index 0000000..c8c29ef --- /dev/null +++ b/src/main/java/org/gcube/common/authorizationservice/configuration/AuthorizationRule.java @@ -0,0 +1,89 @@ +package org.gcube.common.authorizationservice.configuration; + +import java.util.ArrayList; +import java.util.List; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +@XmlRootElement(name="Rule") +@XmlAccessorType(XmlAccessType.FIELD) +public class AuthorizationRule { + + + @XmlAttribute(name="path") + private String servletPath; + + @XmlAttribute(name="requiresToken") + private boolean requiresToken = true; + + @XmlElement(name="Entity") + private List entities= new ArrayList(); + + protected AuthorizationRule(){} + + public AuthorizationRule(String servletPath, List entities, boolean requiresToken) { + super(); + this.servletPath = servletPath; + this.entities = entities; + this.requiresToken = requiresToken; + } + + public String getServletPath() { + return servletPath; + } + + public List getEntities() { + return entities; + } + + + public boolean isTokenRequired() { + return requiresToken; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + + ((entities == null) ? 0 : entities.hashCode()); + result = prime * result + + ((servletPath == null) ? 0 : servletPath.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + AuthorizationRule other = (AuthorizationRule) obj; + if (entities == null) { + if (other.entities != null) + return false; + } else if (!entities.equals(other.entities)) + return false; + if (servletPath == null) { + if (other.servletPath != null) + return false; + } else if (!servletPath.equals(other.servletPath)) + return false; + return true; + } + + @Override + public String toString() { + return "AuthorizationRule [servletPath=" + servletPath + ", entities=" + + entities + " requiresToken= "+requiresToken+"]"; + } + + + +} diff --git a/src/main/java/org/gcube/common/authorizationservice/configuration/ConfigurationBuilder.java b/src/main/java/org/gcube/common/authorizationservice/configuration/ConfigurationBuilder.java new file mode 100644 index 0000000..4be30b2 --- /dev/null +++ b/src/main/java/org/gcube/common/authorizationservice/configuration/ConfigurationBuilder.java @@ -0,0 +1,35 @@ +package org.gcube.common.authorizationservice.configuration; + +import java.util.ArrayList; +import java.util.List; + +public class ConfigurationBuilder { + + + List rules = new ArrayList(); + + List ips = new ArrayList(); + + public static ConfigurationBuilder getBuilder(){ + return new ConfigurationBuilder(); + } + + public ConfigurationBuilder rule(AuthorizationRule rule){ + this.rules.add(rule); + return this; + } + + public ConfigurationBuilder autoConfirmedIp(String ip){ + this.ips.add(ip); + return this; + } + + public AuthorizationConfiguration build(){ + AuthorizationConfiguration configuration = new AuthorizationConfiguration(); + configuration.setAuthorizationRules(rules); + configuration.setAllowedContainerIps(ips); + return configuration; + } + + +} diff --git a/src/main/java/org/gcube/common/authorizationservice/configuration/ConfigurationHolder.java b/src/main/java/org/gcube/common/authorizationservice/configuration/ConfigurationHolder.java new file mode 100644 index 0000000..babc15e --- /dev/null +++ b/src/main/java/org/gcube/common/authorizationservice/configuration/ConfigurationHolder.java @@ -0,0 +1,22 @@ +package org.gcube.common.authorizationservice.configuration; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class ConfigurationHolder { + + private static Logger logger = LoggerFactory.getLogger(ConfigurationHolder.class); + + private static AuthorizationConfiguration configuration; + + public static AuthorizationConfiguration getConfiguration() { + logger.trace("getting configuration {}",configuration); + return configuration; + } + + public static void setConfiguration(AuthorizationConfiguration authConfiguration) { + logger.trace("setting configuration {}",authConfiguration); + configuration = authConfiguration; + } + +} diff --git a/src/main/java/org/gcube/common/authorizationservice/configuration/RuleBuilder.java b/src/main/java/org/gcube/common/authorizationservice/configuration/RuleBuilder.java new file mode 100644 index 0000000..111b9d3 --- /dev/null +++ b/src/main/java/org/gcube/common/authorizationservice/configuration/RuleBuilder.java @@ -0,0 +1,47 @@ +package org.gcube.common.authorizationservice.configuration; + +import java.util.ArrayList; +import java.util.List; + + +public class RuleBuilder { + + private String servletPath; + + private List entities = new ArrayList(); + + private boolean requiresToken= true; + + public RuleBuilder(){} + + public RuleBuilder path(String servletPath){ + this.servletPath = servletPath; + return this; + } + + public RuleBuilder entity(AllowedEntity entity){ + this.entities.add(entity); + return this; + } + + public RuleBuilder needsToken(boolean needsToken){ + this.requiresToken= needsToken; + return this; + } + + protected String getServletPath() { + return servletPath; + } + + protected List getEntities() { + return entities; + } + + protected boolean isRequiresToken() { + return requiresToken; + } + + public AuthorizationRule build(){ + return new AuthorizationRule(servletPath, entities, requiresToken); + } +} \ No newline at end of file diff --git a/src/main/java/org/gcube/common/authorizationservice/filters/ApplicationInitializer.java b/src/main/java/org/gcube/common/authorizationservice/filters/ApplicationInitializer.java new file mode 100644 index 0000000..cb2c80b --- /dev/null +++ b/src/main/java/org/gcube/common/authorizationservice/filters/ApplicationInitializer.java @@ -0,0 +1,36 @@ +package org.gcube.common.authorizationservice.filters; + +import javax.servlet.ServletContextEvent; +import javax.servlet.ServletContextListener; +import javax.servlet.annotation.WebListener; +import javax.xml.bind.JAXBContext; + +import lombok.extern.slf4j.Slf4j; + +import org.gcube.common.authorizationservice.configuration.AuthorizationConfiguration; +import org.gcube.common.authorizationservice.configuration.ConfigurationHolder; + +@WebListener +@Slf4j +public class ApplicationInitializer implements ServletContextListener{ + + + + @Override + public void contextInitialized(ServletContextEvent sce) { + log.info("initilaizing the context"); + try { + JAXBContext context = JAXBContext.newInstance(AuthorizationConfiguration.class); + ConfigurationHolder.setConfiguration( + (AuthorizationConfiguration)context.createUnmarshaller().unmarshal( + sce.getServletContext().getResourceAsStream("WEB-INF/AuthorizationConfiguration.xml"))); + } catch (Exception e) { + log.error("error loading configuration", e); + } + log.info("context initialized"); + } + + @Override + public void contextDestroyed(ServletContextEvent sce) { + } +} diff --git a/src/main/java/org/gcube/common/authorizationservice/filters/AuthorizedCallFilter.java b/src/main/java/org/gcube/common/authorizationservice/filters/AuthorizedCallFilter.java new file mode 100644 index 0000000..2c2575c --- /dev/null +++ b/src/main/java/org/gcube/common/authorizationservice/filters/AuthorizedCallFilter.java @@ -0,0 +1,154 @@ +package org.gcube.common.authorizationservice.filters; + + +import java.io.IOException; +import java.util.List; + +import javax.inject.Inject; +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.annotation.WebFilter; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import lombok.extern.slf4j.Slf4j; + +import org.gcube.common.authorization.library.AuthorizationEntry; +import org.gcube.common.authorizationservice.configuration.AllowedEntity; +import org.gcube.common.authorizationservice.configuration.AuthorizationConfiguration; +import org.gcube.common.authorizationservice.configuration.AuthorizationRule; +import org.gcube.common.authorizationservice.configuration.ConfigurationHolder; +import org.gcube.common.authorizationservice.util.TokenPersistence; + +@WebFilter(urlPatterns={"/*"}, filterName="authorizationFilter") +@Slf4j +public class AuthorizedCallFilter implements Filter { + + private static final String TOKEN_HEADER="gcube-token"; + + public static final String AUTH_ATTRIBUTE="authorizationInfo"; + + @Inject + TokenPersistence persistence; + + @Override + public void init(FilterConfig filterConfig) throws ServletException { + + } + + @Override + public void doFilter(ServletRequest request, ServletResponse response, + FilterChain chain) throws IOException, ServletException { + + String token = request.getParameter(TOKEN_HEADER)==null?((HttpServletRequest)request).getHeader(TOKEN_HEADER): + request.getParameter(TOKEN_HEADER); + + AuthorizationEntry info = null; + if (token!=null){ + info = persistence.getAuthorizationEntry(token); + log.info("call from {} ",info); + } else log.info("call without token"); + + request.setAttribute(AUTH_ATTRIBUTE, info); + + String pathInfo = ((HttpServletRequest) request).getPathInfo(); + log.info("called path {}", pathInfo); + + if (requiresToken(pathInfo) && token==null ){ + ((HttpServletResponse)response).sendError(HttpServletResponse.SC_UNAUTHORIZED); + log.info("call rejected from filters, call requires caller token"); + return; + } + + + String callerIp = ((HttpServletRequest)request).getHeader("x-forwarded-for"); + if(callerIp==null) + callerIp=request.getRemoteHost(); + log.info("caller ip {}", callerIp); + + /*X509Certificate certs[] = + (X509Certificate[])req.getAttribute("javax.servlet.request.X509Certificate"); + // ... Test if non-null, non-empty. + + X509Certificate clientCert = certs[0]; + + // Get the Subject DN's X500Principal + X500Principal subjectDN = clientCert.getSubjectX500Principal();*/ + + if (!checkAllowed(pathInfo, callerIp, info)){ + ((HttpServletResponse)response).sendError(HttpServletResponse.SC_UNAUTHORIZED); + log.info("call rejected from filters"); + return; + } + + chain.doFilter(request, response); + } + + private boolean requiresToken(String pathInfo) { + AuthorizationConfiguration conf = ConfigurationHolder.getConfiguration(); + List rules = conf.getAuthorizationRules(); + for (AuthorizationRule rule: rules) + if (pathInfo.startsWith(rule.getServletPath()) || pathInfo.equals(rule.getServletPath())) + return rule.isTokenRequired(); + return false; + } + + private boolean checkAllowed(String pathInfo, String callerIp, AuthorizationEntry info){ + AuthorizationConfiguration conf = ConfigurationHolder.getConfiguration(); + List rules = conf.getAuthorizationRules(); + for (AuthorizationRule rule: rules){ + if (!rule.getEntities().isEmpty() && (pathInfo.startsWith(rule.getServletPath()) || pathInfo.equals(rule.getServletPath()))){ + for (AllowedEntity entity : rule.getEntities()){ + switch(entity.getType()){ + case IP: + log.trace("checking ip rule : {} -> {}", entity.getValue(), callerIp); + if(checkIpInRange(callerIp, entity.getValue())) + return true; + break; + case USER: + log.trace("checking user rule : {} -> {}", entity.getValue(), info.getClientInfo().getId()); + if (entity.getValue().equals(info.getClientInfo().getId())) + return entity.getValue().equals(info.getClientInfo().getId()); + break; + case ROLE: + log.trace("checking role rule : {} -> {}", entity.getValue(), info.getClientInfo().getRoles()); + if (info.getClientInfo().getRoles().contains(entity.getValue())) + return true; + break; + } + } + //IF a servlet path matches the caller is not allowed to that servlet (the call should be rejected) + return false; + } + } + return true; + } + + + private static boolean checkIpInRange(String ip, String mask) { + + String[] maskArray = mask.split("\\."); + String[] ipArray = ip.split("\\."); + + int[] maskByte= new int[4]; + int[] ipByte = new int[4]; + + for (int i=0; i<4; i++){ + maskByte[i] = ((Integer)Integer.parseInt(maskArray[i])).byteValue(); + ipByte[i] = ((Integer)Integer.parseInt(ipArray[i])).byteValue(); + } + return (maskByte[0]==0 || maskByte[0]==ipByte[0]) && (maskByte[1]==0 || maskByte[1]==ipByte[1]) && + (maskByte[2]==0 || maskByte[2]==ipByte[2]) && (maskByte[3]==0 || maskByte[3]==ipByte[3]); + + } + + + @Override + public void destroy() {} + + +} diff --git a/src/main/java/org/gcube/common/authorizationservice/persistence/RelationDBPersistence.java b/src/main/java/org/gcube/common/authorizationservice/persistence/RelationDBPersistence.java new file mode 100644 index 0000000..9e83a5c --- /dev/null +++ b/src/main/java/org/gcube/common/authorizationservice/persistence/RelationDBPersistence.java @@ -0,0 +1,322 @@ +package org.gcube.common.authorizationservice.persistence; + +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.inject.Inject; +import javax.inject.Singleton; +import javax.persistence.EntityManager; +import javax.persistence.EntityManagerFactory; +import javax.persistence.NoResultException; +import javax.persistence.TypedQuery; + +import lombok.extern.slf4j.Slf4j; + +import org.gcube.common.authorization.library.AuthorizationEntry; +import org.gcube.common.authorization.library.policies.Policy; +import org.gcube.common.authorization.library.policies.PolicyType; +import org.gcube.common.authorization.library.policies.Service2ServicePolicy; +import org.gcube.common.authorization.library.policies.User2ServicePolicy; +import org.gcube.common.authorization.library.provider.ClientInfo; +import org.gcube.common.authorization.library.provider.ContainerInfo; +import org.gcube.common.authorization.library.provider.ExternalServiceInfo; +import org.gcube.common.authorization.library.provider.ServiceIdentifier; +import org.gcube.common.authorization.library.provider.ServiceInfo; +import org.gcube.common.authorization.library.provider.UserInfo; +import org.gcube.common.authorizationservice.persistence.entities.AuthorizationEntity; +import org.gcube.common.authorizationservice.persistence.entities.AuthorizationId; +import org.gcube.common.authorizationservice.persistence.entities.EntityConstants; +import org.gcube.common.authorizationservice.persistence.entities.ExternalServiceAuthorizationEntity; +import org.gcube.common.authorizationservice.persistence.entities.NodeAuthorizationEntity; +import org.gcube.common.authorizationservice.persistence.entities.PolicyEntity; +import org.gcube.common.authorizationservice.persistence.entities.ServiceAuthorizationEntity; +import org.gcube.common.authorizationservice.persistence.entities.ServicePolicyEntity; +import org.gcube.common.authorizationservice.persistence.entities.UserAuthorizationEntity; +import org.gcube.common.authorizationservice.persistence.entities.UserPolicyEntity; +import org.gcube.common.authorizationservice.util.TokenPersistence; + +@Singleton +@Slf4j +public class RelationDBPersistence implements TokenPersistence{ + + @Inject + EntityManagerFactory emFactory; + + //ONLY FOR TEST PURPOSE + public void setEntitymanagerFactory(EntityManagerFactory emf){ + this.emFactory = emf; + } + + @Override + public AuthorizationEntry getAuthorizationEntry(String token) { + EntityManager em = emFactory.createEntityManager(); + try{ + //retrieve entity for token + TypedQuery query = em.createNamedQuery("Authz.get", AuthorizationEntity.class); + query.setParameter("token", token); + AuthorizationEntity authEntity; + try{ + em.getTransaction().begin(); + authEntity = query.getSingleResult(); + authEntity.setLastTimeUsed(Calendar.getInstance()); + em.merge(authEntity); + em.getTransaction().commit(); + }catch (NoResultException e){ + log.warn("no result found for token {}",token); + return null; + } + + if (authEntity.getEntryType().equals(EntityConstants.SERVICE_AUTHORIZATION)){ + ServiceAuthorizationEntity sAuth = (ServiceAuthorizationEntity) authEntity; + return new AuthorizationEntry(sAuth.getInfo(), sAuth.getContext(), retrievePolicies(sAuth, em), sAuth.getQualifier()); + } else if (authEntity.getEntryType().equals(EntityConstants.USER_AUTHORIZATION)){ + UserAuthorizationEntity uAuth = (UserAuthorizationEntity) authEntity; + return new AuthorizationEntry(uAuth.getInfo(), uAuth.getContext(), retrievePolicies(uAuth, em), uAuth.getQualifier()); + } else if (authEntity.getEntryType().equals(EntityConstants.EXTERNAL_SERVICE_AUTHORIZATION)){ + ExternalServiceAuthorizationEntity uAuth = (ExternalServiceAuthorizationEntity) authEntity; + return new AuthorizationEntry(uAuth.getInfo(), uAuth.getContext(), new ArrayList(), uAuth.getQualifier()); + } else if (authEntity.getEntryType().equals(EntityConstants.CONTAINER_AUTHORIZATION)){ + NodeAuthorizationEntity uAuth = (NodeAuthorizationEntity) authEntity; + return new AuthorizationEntry(uAuth.getInfo(), uAuth.getContext(), new ArrayList(), uAuth.getQualifier()); + } else throw new IllegalArgumentException("entryType cannot be mapped"); + }catch(Throwable t){ + log.error("error retrieving authorization entry",t); + return null; + }finally{ + em.close(); + } + } + + @Override + public String getExistingToken(String clientId, String context, String qualifier) { + EntityManager em = emFactory.createEntityManager(); + try{ + AuthorizationEntity authEntity = em.find(AuthorizationEntity.class, new AuthorizationId(context, clientId, qualifier)); + if (authEntity!=null) + return authEntity.getToken(); + return null; + }finally{ + em.close(); + } + + } + + @Override + public void saveAuthorizationEntry(String token, String context, + ClientInfo info, String tokenQualifier, String generatedBy) { + AuthorizationEntity authEntity = null; + if (info instanceof UserInfo) + authEntity = new UserAuthorizationEntity(token, context, tokenQualifier, (UserInfo) info); + else if (info instanceof ServiceInfo) authEntity = new ServiceAuthorizationEntity(token, context, tokenQualifier, (ServiceInfo) info, generatedBy); + else if (info instanceof ExternalServiceInfo) authEntity = new ExternalServiceAuthorizationEntity(token, context, tokenQualifier, (ExternalServiceInfo) info, generatedBy); + else authEntity = new NodeAuthorizationEntity(token, context, tokenQualifier, (ContainerInfo) info, generatedBy); + + EntityManager em = emFactory.createEntityManager(); + try{ + em.getTransaction().begin(); + em.persist(authEntity); + em.getTransaction().commit(); + }catch(RuntimeException e){ + log.error("error saving authorization Entry", e); + em.getTransaction().rollback(); + throw e; + } finally{ + em.close(); + } + + } + + + @Override + public void addPolicies(List polices) { + EntityManager em = emFactory.createEntityManager(); + try{ + em.getTransaction().begin(); + for (Policy policy: polices) + if (policy.getPolicyType()==PolicyType.SERVICE){ + Service2ServicePolicy s2sPolicy = (Service2ServicePolicy) policy; + em.persist(new ServicePolicyEntity(s2sPolicy.getContext(), s2sPolicy.getServiceAccess(), s2sPolicy.getClient(), s2sPolicy.getMode())); + } else { + User2ServicePolicy u2sPolicy = (User2ServicePolicy) policy; + em.persist(new UserPolicyEntity(u2sPolicy.getContext(), u2sPolicy.getServiceAccess(), u2sPolicy.getEntity(), u2sPolicy.getMode())); + } + + em.getTransaction().commit(); + }catch (Exception e) { + em.close(); + } + } + + @Override + public void removePolicy(long policyId) { + EntityManager em = emFactory.createEntityManager(); + try{ + em.getTransaction().begin(); + PolicyEntity entity = em.find(PolicyEntity.class, policyId); + if (entity!= null){ + em.remove(entity); + //TODO: throw an exception + } + else log.warn("policy with id {} not found", policyId); + em.getTransaction().commit(); + }catch (Exception e) { + log.error("error removing policy with id {}", policyId); + em.close(); + } + } + + @Override + public List getPolices(String context) { + List policiesToReturn = new ArrayList(); + EntityManager em = emFactory.createEntityManager(); + try{ + TypedQuery query = em.createNamedQuery("Policy.all", PolicyEntity.class); + query.setParameter("context", context); + for (PolicyEntity pEntity: query.getResultList()){ + Policy policy; + if (pEntity.getPolicyType().equals(EntityConstants.SERVICE_POLICY)){ + policy = new Service2ServicePolicy(context, pEntity.getServiceAccess(), ((ServicePolicyEntity) pEntity).getClientAccess(), pEntity.getAction()); + }else + policy = new User2ServicePolicy(context, pEntity.getServiceAccess(), ((UserPolicyEntity) pEntity).getUser(), pEntity.getAction()); + policy.setId(pEntity.getId()); + policy.setCreationTime(pEntity.getCreationTime()); + policy.setLastUpdateTime(pEntity.getLastUpdateTime()); + policiesToReturn.add(policy); + } + }finally{ + em.close(); + } + return policiesToReturn; + } + + @Override + public List getPolicesByType(String context, PolicyType type) { + // TODO Auto-generated method stub + return null; + } + + @Override + public List getPolicesByTypeAndClientId(String context, PolicyType type, String clientId) { + // TODO Auto-generated method stub + return null; + } + + private List retrievePolicies(UserAuthorizationEntity uAuth, EntityManager em){ + List policies = new ArrayList(); + + + TypedQuery queryU = em.createNamedQuery("UserPolicy.get", UserPolicyEntity.class); + queryU.setParameter("context", uAuth.getContext()); + queryU.setParameter("user", uAuth.getInfo().getId()); + if (!uAuth.getInfo().getRoles().isEmpty()) + queryU.setParameter("rolesList", uAuth.getInfo().getRoles()); + else queryU.setParameter("rolesList", Collections.singleton("")); + List userPolicies = queryU.getResultList(); + + + for (UserPolicyEntity uPolicy: userPolicies){ + User2ServicePolicy u2sP = new User2ServicePolicy(uPolicy.getContext(), uPolicy.getServiceAccess(), uPolicy.getUser(), uPolicy.getAction()); + u2sP.setCreationTime(uPolicy.getCreationTime()); + u2sP.setLastUpdateTime(uPolicy.getLastUpdateTime()); + policies.add(u2sP); + } + log.debug("user policies found are {}", policies); + + return policies; + } + + private List retrievePolicies(ServiceAuthorizationEntity sAuth, EntityManager em){ + + List policies = new ArrayList(); + ServiceIdentifier sIdentifier = ((ServiceInfo)sAuth.getInfo()).getServiceIdentifier(); + + TypedQuery queryS = em.createNamedQuery("ServicePolicy.get", ServicePolicyEntity.class); + queryS.setParameter("context", sAuth.getContext()); + + queryS.setParameter("serviceClass", sIdentifier.getServiceClass()); + queryS.setParameter("serviceName", sIdentifier.getServiceName()); + queryS.setParameter("identifier", sIdentifier.getServiceId()); + + List servicePolicies = queryS.getResultList(); + + for (ServicePolicyEntity sPolicy: servicePolicies){ + Service2ServicePolicy s2sP = new Service2ServicePolicy(sPolicy.getContext(), sPolicy.getServiceAccess(), sPolicy.getClientAccess(), sPolicy.getAction()); + s2sP.setCreationTime(sPolicy.getCreationTime()); + s2sP.setLastUpdateTime(sPolicy.getLastUpdateTime()); + policies.add(s2sP); + } + log.debug("service policies found are {}", policies); + + return policies; + } + + @Override + public Map getExistingApiKeys(String clientId, String context) { + EntityManager em = emFactory.createEntityManager(); + + try{ + TypedQuery queryS = em.createNamedQuery("Authz.getQualifiers", AuthorizationEntity.class); + queryS.setParameter("context", context); + queryS.setParameter("clientId", clientId); + List apikeys = queryS.getResultList(); + Map qualifiers = new HashMap(); + for (AuthorizationEntity apikey: apikeys) + qualifiers.put(apikey.getQualifier(), apikey.getToken()); + return qualifiers; + }finally{ + em.close(); + } + + + } + + @Override + public void removeApiKey(String token) { + EntityManager em = emFactory.createEntityManager(); + try{ + em.getTransaction().begin(); + TypedQuery queryS = em.createNamedQuery("Authz.getByToken", AuthorizationEntity.class); + queryS.setParameter("token", token); + AuthorizationEntity authEntry = queryS.getSingleResult(); + if (authEntry != null) + em.remove(authEntry); + em.getTransaction().commit(); + }catch (Exception e) { + log.error("error removing apikey {}", token); + em.close(); + } + } + + + + /* @Override + public Key getSymmetricKey(String token) { + EntityManager em = emFactory.createEntityManager(); + try{ + //retrieve entity for token + TypedQuery query = em.createNamedQuery("Authz.get", AuthorizationEntity.class); + query.setParameter("token", token); + AuthorizationEntity authEntity; + try{ + authEntity = query.getSingleResult(); + }catch (NoResultException e){ + log.warn("no result found for token {}",token); + return null; + } + + return authEntity.getApiSymmetricKey(); + + }catch(Throwable t){ + log.error("error retrieving key fro token {}",token, t); + return null; + }finally{ + em.close(); + } + }*/ + + +} diff --git a/src/main/java/org/gcube/common/authorizationservice/persistence/entities/AuthorizationEntity.java b/src/main/java/org/gcube/common/authorizationservice/persistence/entities/AuthorizationEntity.java new file mode 100644 index 0000000..35661c8 --- /dev/null +++ b/src/main/java/org/gcube/common/authorizationservice/persistence/entities/AuthorizationEntity.java @@ -0,0 +1,236 @@ +package org.gcube.common.authorizationservice.persistence.entities; + +import java.util.Calendar; +import java.util.List; + +import javax.persistence.Column; +import javax.persistence.Convert; +import javax.persistence.DiscriminatorColumn; +import javax.persistence.Embeddable; +import javax.persistence.Embedded; +import javax.persistence.EmbeddedId; +import javax.persistence.Entity; +import javax.persistence.Inheritance; +import javax.persistence.NamedQueries; +import javax.persistence.NamedQuery; +import javax.persistence.Table; +import javax.persistence.Temporal; +import javax.persistence.TemporalType; +import javax.persistence.Transient; + +import org.gcube.common.authorization.library.provider.ClientInfo; +import org.gcube.common.authorization.library.provider.ContainerInfo; +import org.gcube.common.authorization.library.provider.ExternalServiceInfo; +import org.gcube.common.authorization.library.provider.ServiceIdentifier; +import org.gcube.common.authorization.library.provider.ServiceInfo; +import org.gcube.common.authorization.library.provider.UserInfo; +import org.gcube.common.authorizationservice.persistence.entities.ServicePolicyEntity.ServiceAccessEntity; +import org.gcube.common.authorizationservice.persistence.entities.converters.StringListConverter; +import org.gcube.common.authorizationservice.util.Constants; +import org.jboss.weld.exceptions.IllegalArgumentException; + +@Entity +@Inheritance +@DiscriminatorColumn(name="EntryType") +@Table(name="Authorizations") +@NamedQueries({ + @NamedQuery(name="Authz.get", query="SELECT DISTINCT info FROM AuthorizationEntity info WHERE " + + " info.token=:token"), + @NamedQuery(name="Authz.getQualifiers", query="SELECT DISTINCT info FROM AuthorizationEntity info WHERE " + + " info.id.qualifier!='"+Constants.DEFAULT_TOKEN_QUALIFIER+"' AND info.id.clientId=:clientId AND info.id.context=:context"), + @NamedQuery(name="Authz.getByToken", query="SELECT DISTINCT info FROM AuthorizationEntity info WHERE " + + " info.token=:token") +}) +public abstract class AuthorizationEntity { + + + private static final String DEFAULT_GENERATOR ="default"; + + @EmbeddedId + AuthorizationId id; + + @Column(unique=true) + String token; + + @Column + String generatedBy = DEFAULT_GENERATOR; + + @Transient + ClientInfo info; + + @Embedded + private ClientInfoEntity internalInfo; + + @Temporal(TemporalType.TIMESTAMP) + @Column + Calendar creationTime; + + @Temporal(TemporalType.TIMESTAMP) + @Column(nullable=true) + Calendar lastTimeUsed; + + @Column(name="EntryType") + String entryType; + + protected AuthorizationEntity() { + super(); + } + + public AuthorizationEntity(String token, String context, ClientInfo clientInfo, String qualifier, String entryType ) { + super(); + this.id = new AuthorizationId(context, clientInfo.getId(), qualifier); + this.token = token; + this.entryType = entryType; + this.creationTime = Calendar.getInstance(); + this.info = clientInfo; + this.internalInfo = retriveInternalInfo(this.info); + } + + public AuthorizationEntity(String token, String context, ClientInfo clientInfo, String qualifier, String entryType, String generatedBy ) { + this(token, context, clientInfo, qualifier, entryType); + this.generatedBy = generatedBy; + } + + public String getToken() { + return this.token; + } + + public String getContext() { + return id.context; + } + + public String getClientId() { + return id.clientId; + } + + public ClientInfo getInfo() { + if (this.info == null) + this.info = retieveInfo(); + + return this.info; + } + + public String getEntryType() { + return entryType; + } + + public String getGeneratedBy() { + return generatedBy; + } + + public void setGeneratedBy(String generatedBy) { + this.generatedBy = generatedBy; + } + + public String getQualifier(){ + return id.qualifier; + } + + public Calendar getLastTimeUsed() { + return lastTimeUsed; + } + + public void setLastTimeUsed(Calendar lastTimeUsed) { + this.lastTimeUsed = lastTimeUsed; + } + + private ClientInfo retieveInfo() { + switch (entryType) { + case EntityConstants.USER_AUTHORIZATION: + return new UserInfo(this.internalInfo.identifier, this.internalInfo.roles); + case EntityConstants.SERVICE_AUTHORIZATION: + return new ServiceInfo(new ServiceIdentifier(this.internalInfo.service.clientServiceClass, this.internalInfo.service.clientServiceName, this.internalInfo.service.clientServiceIdentifier)); + case EntityConstants.EXTERNAL_SERVICE_AUTHORIZATION: + return new ExternalServiceInfo(this.internalInfo.identifier, this.internalInfo.generatedBy); + case EntityConstants.CONTAINER_AUTHORIZATION: + return new ContainerInfo(this.internalInfo.host, this.internalInfo.port); + default: + throw new IllegalArgumentException("invalid entity type"); + } + + } + + private ClientInfoEntity retriveInternalInfo(ClientInfo info2) { + switch (entryType) { + case EntityConstants.USER_AUTHORIZATION: + return ClientInfoEntity.forUser(info.getId(), info.getRoles()); + case EntityConstants.SERVICE_AUTHORIZATION: + ServiceIdentifier identifier = ((ServiceInfo) this.info).getServiceIdentifier(); + return ClientInfoEntity.forService(identifier.getServiceClass(), identifier.getServiceName(), identifier.getServiceId()); + case EntityConstants.EXTERNAL_SERVICE_AUTHORIZATION: + ExternalServiceInfo externalServiceInfo = (ExternalServiceInfo) this.info; + return ClientInfoEntity.forExternalService(externalServiceInfo.getId(), externalServiceInfo.getGeneratedBy()); + case EntityConstants.CONTAINER_AUTHORIZATION: + ContainerInfo containerInfo = (ContainerInfo) this.info; + return ClientInfoEntity.forContainer(containerInfo.getHost(), containerInfo.getPort()); + default: + throw new IllegalArgumentException("invalid entity type"); + } + } + + @Override + public String toString() { + return "AuthorizationEntity [id=" + id + ", token=" + token + + ", creationTime=" + creationTime + ", entryType=" + entryType + + "]"; + } + + @Embeddable + private static class ClientInfoEntity { + + // userInfo + @Column(name="info_identifier") + private String identifier; + + @Column(name="info_roles", length=2000) + @Convert(converter=StringListConverter.class) + private List roles; + + //serviceInfo + @Embedded + private ServiceAccessEntity service; + + //external service info + @Column(name="info_generatedby") + private String generatedBy; + + //containerInfo + @Column(name="info_host") + private String host; + @Column(name="info_port") + private int port; + + protected static ClientInfoEntity forExternalService(String identifier, String generatedBy){ + ClientInfoEntity entry =new ClientInfoEntity(); + entry.generatedBy= generatedBy; + entry.identifier = identifier; + return entry; + } + + protected static ClientInfoEntity forService(String serviceClass, String serviceName, String serviceId){ + ClientInfoEntity entry =new ClientInfoEntity(); + ServiceAccessEntity service = new ServiceAccessEntity(); + service.clientServiceClass = serviceClass; + service.clientServiceName = serviceName; + service.clientServiceIdentifier = serviceId; + entry.service = service; + return entry; + + } + + protected static ClientInfoEntity forUser(String identifier, List roles){ + ClientInfoEntity entry =new ClientInfoEntity(); + entry.roles= roles; + entry.identifier = identifier; + return entry; + } + + protected static ClientInfoEntity forContainer(String host, int port){ + ClientInfoEntity entry =new ClientInfoEntity(); + entry.host = host; + entry.port = port; + return entry; + } + + } +} diff --git a/src/main/java/org/gcube/common/authorizationservice/persistence/entities/AuthorizationId.java b/src/main/java/org/gcube/common/authorizationservice/persistence/entities/AuthorizationId.java new file mode 100644 index 0000000..3527cd0 --- /dev/null +++ b/src/main/java/org/gcube/common/authorizationservice/persistence/entities/AuthorizationId.java @@ -0,0 +1,30 @@ +package org.gcube.common.authorizationservice.persistence.entities; + +import javax.persistence.Embeddable; + +@Embeddable +public class AuthorizationId { + + String context; + String clientId; + String qualifier; + + protected AuthorizationId() { + super(); + } + + public AuthorizationId(String context, String clientId, String qualifier) { + super(); + this.context = context; + this.clientId = clientId; + this.qualifier = qualifier; + } + + @Override + public String toString() { + return "AuthorizationId [context=" + context + + ", clientId=" + clientId + " qualifier ="+qualifier+"]"; + } + + +} diff --git a/src/main/java/org/gcube/common/authorizationservice/persistence/entities/EntityConstants.java b/src/main/java/org/gcube/common/authorizationservice/persistence/entities/EntityConstants.java new file mode 100644 index 0000000..63047ff --- /dev/null +++ b/src/main/java/org/gcube/common/authorizationservice/persistence/entities/EntityConstants.java @@ -0,0 +1,13 @@ +package org.gcube.common.authorizationservice.persistence.entities; + +public class EntityConstants { + + public static final String USER_POLICY="UserPolicy"; + public static final String SERVICE_POLICY="ServicePolicy"; + + public static final String USER_AUTHORIZATION="UserInfo"; + public static final String SERVICE_AUTHORIZATION="ServiceInfo"; + public static final String EXTERNAL_SERVICE_AUTHORIZATION="ExternalServiceInfo"; + public static final String CONTAINER_AUTHORIZATION="ContainerServiceInfo"; + +} diff --git a/src/main/java/org/gcube/common/authorizationservice/persistence/entities/EntityQueries.java b/src/main/java/org/gcube/common/authorizationservice/persistence/entities/EntityQueries.java new file mode 100644 index 0000000..a4f85be --- /dev/null +++ b/src/main/java/org/gcube/common/authorizationservice/persistence/entities/EntityQueries.java @@ -0,0 +1,32 @@ +package org.gcube.common.authorizationservice.persistence.entities; + +public class EntityQueries { + + public static final String SERVICE_POLICY_GET ="SELECT DISTINCT p FROM ServicePolicyEntity p LEFT JOIN FETCH p.excludes ae WHERE " + + " p.context=:context AND (( p.excludeType=org.gcube.common.authorizationservice.persistence.entities.ExcludeType.NOTEXCLUDE " + + " AND (( p.clientAccessEntity.clientServiceClass = null AND p.clientAccessEntity.clientServiceName=null AND p.clientAccessEntity.clientServiceIdentifier=null) OR" + + " ( p.clientAccessEntity.clientServiceClass = :serviceClass AND p.clientAccessEntity.clientServiceName=null AND p.clientAccessEntity.clientServiceIdentifier=null) OR" + + " ( p.clientAccessEntity.clientServiceClass = :serviceClass AND p.clientAccessEntity.clientServiceName=:serviceName AND p.clientAccessEntity.clientServiceIdentifier=null) OR" + + " ( p.clientAccessEntity.clientServiceClass = :serviceClass AND p.clientAccessEntity.clientServiceName=:serviceName AND p.clientAccessEntity.clientServiceIdentifier=:identifier)))" + + " OR ( p.excludeType=org.gcube.common.authorizationservice.persistence.entities.ExcludeType.EXCLUDE AND NOT(( ae.clientServiceClass = null AND ae.clientServiceName=null AND ae.clientServiceIdentifier=null) OR" + + " ( ae.clientServiceClass = :serviceClass AND ae.clientServiceName=null AND ae.clientServiceIdentifier=null) OR" + + " ( ae.clientServiceClass = :serviceClass AND ae.clientServiceName=:serviceName AND ae.clientServiceIdentifier=null) OR" + + " ( ae.clientServiceClass = :serviceClass AND ae.clientServiceName=:serviceName AND ae.clientServiceIdentifier=:identifier))))"; + + + + + public static final String USER_POLICY_GET = "SELECT policy FROM UserPolicyEntity policy WHERE " + + " policy.context=:context AND (( policy.type=org.gcube.common.authorization.library.policies.UserEntity$UserEntityType.ROLE AND policy.identifier in :rolesList) " + + "OR (policy.type=org.gcube.common.authorization.library.policies.UserEntity$UserEntityType.USER AND policy.identifier=:user ) OR " + + " ( policy.type=org.gcube.common.authorization.library.policies.UserEntity$UserEntityType.ROLE AND policy.excludes not in :rolesList) OR" + + " (policy.type=org.gcube.common.authorization.library.policies.UserEntity$UserEntityType.USER AND :user not in (policy.excludes)))"; + + + /* + OR (SELECT count(*) FROM p.excludes ae where (( ae.clientServiceClass = null AND ae.clientServiceName=null AND ae.clientServiceIdentifier=null) OR" + + " ( ae.clientServiceClass = :serviceClass AND ae.clientServiceName=null AND ae.clientServiceIdentifier=null) OR" + + " ( ae.clientServiceClass = :serviceClass AND ae.clientServiceName=:serviceName AND ae.clientServiceIdentifier=null) OR" + + " ( ae.clientServiceClass = :serviceClass AND ae.clientServiceName=:serviceName AND ae.clientServiceIdentifier=:identifier))) + */ +} diff --git a/src/main/java/org/gcube/common/authorizationservice/persistence/entities/ExcludeType.java b/src/main/java/org/gcube/common/authorizationservice/persistence/entities/ExcludeType.java new file mode 100644 index 0000000..4a2d3d1 --- /dev/null +++ b/src/main/java/org/gcube/common/authorizationservice/persistence/entities/ExcludeType.java @@ -0,0 +1,6 @@ +package org.gcube.common.authorizationservice.persistence.entities; + +public enum ExcludeType { + + EXCLUDE, NOTEXCLUDE +} diff --git a/src/main/java/org/gcube/common/authorizationservice/persistence/entities/ExternalServiceAuthorizationEntity.java b/src/main/java/org/gcube/common/authorizationservice/persistence/entities/ExternalServiceAuthorizationEntity.java new file mode 100644 index 0000000..03d276f --- /dev/null +++ b/src/main/java/org/gcube/common/authorizationservice/persistence/entities/ExternalServiceAuthorizationEntity.java @@ -0,0 +1,30 @@ +package org.gcube.common.authorizationservice.persistence.entities; + +import javax.persistence.DiscriminatorValue; +import javax.persistence.Entity; +import javax.persistence.NamedQueries; +import javax.persistence.NamedQuery; + +import org.gcube.common.authorization.library.provider.ExternalServiceInfo; + +@Entity +@DiscriminatorValue(EntityConstants.EXTERNAL_SERVICE_AUTHORIZATION) +@NamedQueries({ + @NamedQuery(name="ExternalService.get", query="SELECT info FROM ExternalServiceAuthorizationEntity info WHERE " + + " info.token=:token AND info.id.context=:context AND info.id.clientId=:clientId") +}) +public class ExternalServiceAuthorizationEntity extends AuthorizationEntity{ + + + + @SuppressWarnings("unused") + private ExternalServiceAuthorizationEntity(){} + + public ExternalServiceAuthorizationEntity(String token, String context, String qualifier, + ExternalServiceInfo externalServiceInfo, String generatedBy) { + super(token, context, externalServiceInfo, qualifier, EntityConstants.SERVICE_AUTHORIZATION, generatedBy); + } + + + +} \ No newline at end of file diff --git a/src/main/java/org/gcube/common/authorizationservice/persistence/entities/NodeAuthorizationEntity.java b/src/main/java/org/gcube/common/authorizationservice/persistence/entities/NodeAuthorizationEntity.java new file mode 100644 index 0000000..1f63d8b --- /dev/null +++ b/src/main/java/org/gcube/common/authorizationservice/persistence/entities/NodeAuthorizationEntity.java @@ -0,0 +1,21 @@ +package org.gcube.common.authorizationservice.persistence.entities; + +import javax.persistence.DiscriminatorValue; +import javax.persistence.Entity; + +import org.gcube.common.authorization.library.provider.ContainerInfo; + +@Entity +@DiscriminatorValue(EntityConstants.CONTAINER_AUTHORIZATION) +public class NodeAuthorizationEntity extends AuthorizationEntity{ + + @SuppressWarnings("unused") + private NodeAuthorizationEntity(){} + + public NodeAuthorizationEntity(String token, String context, String qualifier , + ContainerInfo containerInfo, String generatedBy) { + super(token, context, containerInfo, qualifier, EntityConstants.CONTAINER_AUTHORIZATION, generatedBy==null?"UNKNOWN":generatedBy); + } + + +} diff --git a/src/main/java/org/gcube/common/authorizationservice/persistence/entities/PendingEntity.java b/src/main/java/org/gcube/common/authorizationservice/persistence/entities/PendingEntity.java new file mode 100644 index 0000000..39e3374 --- /dev/null +++ b/src/main/java/org/gcube/common/authorizationservice/persistence/entities/PendingEntity.java @@ -0,0 +1,31 @@ +package org.gcube.common.authorizationservice.persistence.entities; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; + +@Entity +@Table +public class PendingEntity { + + @Column + @Id + String containerId; + + @Column(nullable=false) + private String context; + + @Column(nullable=false) + private String key; + + @Column(nullable=false) + private String hostname; + + @Column(nullable=false) + private int port; + + @Column(nullable=false) + private String ip; + +} diff --git a/src/main/java/org/gcube/common/authorizationservice/persistence/entities/PolicyEntity.java b/src/main/java/org/gcube/common/authorizationservice/persistence/entities/PolicyEntity.java new file mode 100644 index 0000000..4555c33 --- /dev/null +++ b/src/main/java/org/gcube/common/authorizationservice/persistence/entities/PolicyEntity.java @@ -0,0 +1,130 @@ +package org.gcube.common.authorizationservice.persistence.entities; + +import java.util.Calendar; + +import javax.persistence.Column; +import javax.persistence.DiscriminatorColumn; +import javax.persistence.Entity; +import javax.persistence.EnumType; +import javax.persistence.Enumerated; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Inheritance; +import javax.persistence.NamedQueries; +import javax.persistence.NamedQuery; +import javax.persistence.Table; +import javax.persistence.Temporal; +import javax.persistence.TemporalType; +import javax.persistence.Transient; + +import org.gcube.common.authorization.library.policies.Action; +import org.gcube.common.authorization.library.policies.ServiceAccess; + +@Entity +@Inheritance +@DiscriminatorColumn(name="PolicyType") +@Table(name="Policies") +@NamedQueries({ + @NamedQuery(name="Policy.all", query="SELECT policy FROM PolicyEntity policy WHERE " + + " policy.context=:context") +}) +public abstract class PolicyEntity { + + @Column + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + protected long id; + + @Column(nullable=false) + private String context; + + @Enumerated(EnumType.ORDINAL) + protected ExcludeType excludeType =ExcludeType.NOTEXCLUDE ; + + @Column(name="PolicyType") + private String policyType; + + @Transient + private ServiceAccess serviceAccess; + + @Column(nullable=true) + private String accessServiceClass; + + @Column(nullable=true) + private String accessServiceName; + + @Column(nullable=true) + private String accessServiceIdentifier; + + @Column(nullable= false) + private Action action; + + @Temporal(TemporalType.TIMESTAMP) + @Column(nullable= false) + private Calendar creationTime; + + @Temporal(TemporalType.TIMESTAMP) + @Column(nullable= false) + private Calendar lastUpdateTime; + + protected PolicyEntity() {} + + public PolicyEntity(String context, ServiceAccess serviceAccess, String policyType, Action action) { + super(); + this.context = context; + this.serviceAccess = serviceAccess; + + if (serviceAccess.getServiceClass()!=null){ + this.accessServiceClass= serviceAccess.getServiceClass(); + if (serviceAccess.getName()!=null){ + this.accessServiceName = serviceAccess.getName(); + if (serviceAccess.getServiceId()!=null) + this.accessServiceIdentifier = serviceAccess.getServiceId(); + } + } + + this.policyType = policyType; + this.action = action; + Calendar now = Calendar.getInstance(); + this.creationTime = now; + this.lastUpdateTime = now; + } + + public long getId() { + return id; + } + + public String getContext() { + return context; + } + + public ServiceAccess getServiceAccess() { + if (serviceAccess==null) + serviceAccess = new ServiceAccess(accessServiceName, accessServiceClass, accessServiceIdentifier); + return serviceAccess; + } + + public String getPolicyType() { + return policyType; + } + + public Action getAction() { + return action; + } + + public Calendar getLastUpdateTime() { + return lastUpdateTime; + } + + public void setLastUpdateTime(Calendar lastUpdateTime) { + this.lastUpdateTime = lastUpdateTime; + } + + public Calendar getCreationTime() { + return creationTime; + } + + public abstract boolean isRewritable(); + +} diff --git a/src/main/java/org/gcube/common/authorizationservice/persistence/entities/ServiceAuthorizationEntity.java b/src/main/java/org/gcube/common/authorizationservice/persistence/entities/ServiceAuthorizationEntity.java new file mode 100644 index 0000000..0f62377 --- /dev/null +++ b/src/main/java/org/gcube/common/authorizationservice/persistence/entities/ServiceAuthorizationEntity.java @@ -0,0 +1,28 @@ +package org.gcube.common.authorizationservice.persistence.entities; + +import javax.persistence.DiscriminatorValue; +import javax.persistence.Entity; +import javax.persistence.NamedQueries; +import javax.persistence.NamedQuery; + +import org.gcube.common.authorization.library.provider.ServiceInfo; + +@Entity +@DiscriminatorValue(EntityConstants.SERVICE_AUTHORIZATION) +@NamedQueries({ + @NamedQuery(name="Service.get", query="SELECT info FROM ServiceAuthorizationEntity info WHERE " + + " info.token=:token AND info.id.context=:context AND info.id.clientId=:clientId") +}) +public class ServiceAuthorizationEntity extends AuthorizationEntity{ + + @SuppressWarnings("unused") + private ServiceAuthorizationEntity(){} + + public ServiceAuthorizationEntity(String token, String context , String qualifier , + ServiceInfo info, String generatedBy) { + super(token, context, info, qualifier, EntityConstants.SERVICE_AUTHORIZATION, generatedBy); + + } + + +} diff --git a/src/main/java/org/gcube/common/authorizationservice/persistence/entities/ServicePolicyEntity.java b/src/main/java/org/gcube/common/authorizationservice/persistence/entities/ServicePolicyEntity.java new file mode 100644 index 0000000..f485ce4 --- /dev/null +++ b/src/main/java/org/gcube/common/authorizationservice/persistence/entities/ServicePolicyEntity.java @@ -0,0 +1,104 @@ +package org.gcube.common.authorizationservice.persistence.entities; + +import java.util.ArrayList; +import java.util.List; + +import javax.persistence.Column; +import javax.persistence.DiscriminatorValue; +import javax.persistence.ElementCollection; +import javax.persistence.Embeddable; +import javax.persistence.Embedded; +import javax.persistence.Entity; +import javax.persistence.NamedQueries; +import javax.persistence.NamedQuery; + +import org.gcube.common.authorization.library.policies.Action; +import org.gcube.common.authorization.library.policies.ServiceAccess; +import org.gcube.common.authorization.library.policies.ServiceEntity; +import org.gcube.common.authorization.library.policies.Services; + +@Entity +@DiscriminatorValue(EntityConstants.SERVICE_POLICY) +@NamedQueries({ + @NamedQuery(name="ServicePolicy.get", query=EntityQueries.SERVICE_POLICY_GET) +}) +public class ServicePolicyEntity extends PolicyEntity { + + @Embedded + ServiceAccessEntity clientAccessEntity = null; + + @ElementCollection + private List excludes; + + protected ServicePolicyEntity() { + super(); + } + + public ServicePolicyEntity(String context, ServiceAccess serviceAccess, ServiceEntity serviceEntityClient, Action mode) { + super(context, serviceAccess, EntityConstants.SERVICE_POLICY, mode); + if (serviceEntityClient.getService()!=null){ + ServiceAccess clientAccess = serviceEntityClient.getService(); + clientAccessEntity = new ServiceAccessEntity(); + clientAccessEntity.clientServiceClass= clientAccess.getServiceClass(); + clientAccessEntity.clientServiceName = clientAccess.getName(); + clientAccessEntity.clientServiceIdentifier = clientAccess.getServiceId(); + this.excludeType = ExcludeType.NOTEXCLUDE; + } else { + excludes = new ArrayList(); + for(ServiceAccess sa : serviceEntityClient.getExcludes()){ + ServiceAccessEntity sae = new ServiceAccessEntity(); + sae.clientServiceClass= sa.getServiceClass(); + sae.clientServiceName = sa.getName(); + sae.clientServiceIdentifier = sa.getServiceId(); + excludes.add(sae); + } + this.excludeType = ExcludeType.EXCLUDE; + } + } + + + public ServiceEntity getClientAccess() { + if (excludes!=null && !excludes.isEmpty()){ + ServiceAccess[] services = new ServiceAccess[excludes.size()]; + for (int i=0;i excludes; + + @Column(nullable=true) + private String identifier; + + protected UserPolicyEntity() {} + + public UserPolicyEntity(String context, ServiceAccess serviceAccess, UserEntity user, Action action) { + super(context, serviceAccess, EntityConstants.USER_POLICY, action); + this.userClient = user; + this.type = user.getType(); + if (user.getIdentifier()!=null){ + this.identifier = user.getIdentifier(); + this.excludeType= ExcludeType.NOTEXCLUDE; + } + else { + this.excludes = user.getExcludes(); + this.excludeType= ExcludeType.EXCLUDE; + } + } + + public UserEntity getUser() { + if (type==UserEntityType.USER){ + if (this.excludeType == ExcludeType.NOTEXCLUDE) + return Users.one(identifier); + else return Users.allExcept(excludes.toArray(new String[excludes.size()])); + } else { + if (this.excludeType == ExcludeType.NOTEXCLUDE) + return Roles.one(identifier); + else return Roles.allExcept(excludes.toArray(new String[excludes.size()])); + + } + } + + @Override + public boolean isRewritable() { + return this.type==UserEntityType.ROLE; + } + + @Override + public String toString() { + return "UserPolicyEntity [userClient=" + userClient + ", type=" + type + + ", excludes=" + excludes + ", identifier=" + identifier + "]"; + } + + +} diff --git a/src/main/java/org/gcube/common/authorizationservice/persistence/entities/converters/StringListConverter.java b/src/main/java/org/gcube/common/authorizationservice/persistence/entities/converters/StringListConverter.java new file mode 100644 index 0000000..3b4af9a --- /dev/null +++ b/src/main/java/org/gcube/common/authorizationservice/persistence/entities/converters/StringListConverter.java @@ -0,0 +1,34 @@ +package org.gcube.common.authorizationservice.persistence.entities.converters; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import javax.persistence.AttributeConverter; +import javax.persistence.Converter; + +@Converter +public class StringListConverter implements AttributeConverter, String>{ + + @Override + public String convertToDatabaseColumn(List list) { + + if (list!=null && list.size()>0){ + StringBuilder builder = new StringBuilder(); + for (String value: list) + builder.append(value).append(",||,"); + return builder.substring(builder.length()-4, builder.length()); + } else return ""; + } + + @Override + public List convertToEntityAttribute(String dbEntry) { + if (dbEntry!=null && !dbEntry.isEmpty()){ + return Arrays.asList(dbEntry.split(",\\|\\|,")); + } + else return new ArrayList(0); + } + + + +} diff --git a/src/main/java/org/gcube/common/authorizationservice/util/CDIProducer.java b/src/main/java/org/gcube/common/authorizationservice/util/CDIProducer.java new file mode 100644 index 0000000..49ca514 --- /dev/null +++ b/src/main/java/org/gcube/common/authorizationservice/util/CDIProducer.java @@ -0,0 +1,14 @@ +package org.gcube.common.authorizationservice.util; + +import javax.enterprise.inject.Produces; +import javax.persistence.EntityManagerFactory; +import javax.persistence.Persistence; + +public class CDIProducer { + + @Produces + EntityManagerFactory createFactory(){ + return Persistence.createEntityManagerFactory("authorization"); + } + +} diff --git a/src/main/java/org/gcube/common/authorizationservice/util/Constants.java b/src/main/java/org/gcube/common/authorizationservice/util/Constants.java new file mode 100644 index 0000000..2248b5b --- /dev/null +++ b/src/main/java/org/gcube/common/authorizationservice/util/Constants.java @@ -0,0 +1,8 @@ +package org.gcube.common.authorizationservice.util; + +public class Constants { + + public static final String PORTAL_ID = "gCubePortal"; + + public static final String DEFAULT_TOKEN_QUALIFIER = "TOKEN"; +} diff --git a/src/main/java/org/gcube/common/authorizationservice/util/TokenPersistence.java b/src/main/java/org/gcube/common/authorizationservice/util/TokenPersistence.java new file mode 100644 index 0000000..93d2f3c --- /dev/null +++ b/src/main/java/org/gcube/common/authorizationservice/util/TokenPersistence.java @@ -0,0 +1,33 @@ +package org.gcube.common.authorizationservice.util; + +import java.util.List; +import java.util.Map; + +import org.gcube.common.authorization.library.AuthorizationEntry; +import org.gcube.common.authorization.library.policies.Policy; +import org.gcube.common.authorization.library.policies.PolicyType; +import org.gcube.common.authorization.library.provider.ClientInfo; + +public interface TokenPersistence { + + void saveAuthorizationEntry(String token, String context, ClientInfo info, String tokenQualifier, String generateBy); + + AuthorizationEntry getAuthorizationEntry(String token); + + String getExistingToken(String clientId, String context, String tokenQualifier); + + Map getExistingApiKeys(String clientId, String context); + + void removeApiKey(String token); + + void addPolicies(List polices); + + void removePolicy(long policyId); + + List getPolices(String context); + + List getPolicesByType(String context, PolicyType type); + + List getPolicesByTypeAndClientId(String context, PolicyType type, + String clientId); +} diff --git a/src/main/resources/META-INF/beans.xml b/src/main/resources/META-INF/beans.xml new file mode 100644 index 0000000..7c7e8db --- /dev/null +++ b/src/main/resources/META-INF/beans.xml @@ -0,0 +1,5 @@ + + \ No newline at end of file diff --git a/src/main/resources/META-INF/persistence.xml b/src/main/resources/META-INF/persistence.xml new file mode 100644 index 0000000..aa54ee4 --- /dev/null +++ b/src/main/resources/META-INF/persistence.xml @@ -0,0 +1,33 @@ + + + + + org.eclipse.persistence.jpa.PersistenceProvider + + + org.gcube.common.authorizationservice.persistence.entities.converters.StringListConverter + + + + org.gcube.common.authorizationservice.persistence.entities.AuthorizationEntity + org.gcube.common.authorizationservice.persistence.entities.ServiceAuthorizationEntity + org.gcube.common.authorizationservice.persistence.entities.UserAuthorizationEntity + org.gcube.common.authorizationservice.persistence.entities.ExternalServiceAuthorizationEntity + org.gcube.common.authorizationservice.persistence.entities.NodeAuthorizationEntity + org.gcube.common.authorizationservice.persistence.entities.PolicyEntity + org.gcube.common.authorizationservice.persistence.entities.ServicePolicyEntity + org.gcube.common.authorizationservice.persistence.entities.UserPolicyEntity + + + + + + + + + + \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/AuthorizationConfiguration.xml b/src/main/webapp/WEB-INF/AuthorizationConfiguration.xml new file mode 100644 index 0000000..d572f2e --- /dev/null +++ b/src/main/webapp/WEB-INF/AuthorizationConfiguration.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/webapp/WEB-INF/gcube-app.xml b/src/main/webapp/WEB-INF/gcube-app.xml new file mode 100644 index 0000000..1dfdbca --- /dev/null +++ b/src/main/webapp/WEB-INF/gcube-app.xml @@ -0,0 +1,10 @@ + + AuthorizationService + Security + 1.0.0-SNAPSHOT + authorization service + + /generate/token/* + /retrieve/* + + diff --git a/src/main/webapp/WEB-INF/web.xml.old b/src/main/webapp/WEB-INF/web.xml.old new file mode 100644 index 0000000..1c0d5be --- /dev/null +++ b/src/main/webapp/WEB-INF/web.xml.old @@ -0,0 +1,9 @@ + + + org.gcube.common.authorizationservice.AuthorizationService + + + org.gcube.common.authorizationservice.AuthorizationService + /gcube/service/* + + \ No newline at end of file diff --git a/src/test/java/org/gcube/common/authz/GenerateTest.java b/src/test/java/org/gcube/common/authz/GenerateTest.java new file mode 100644 index 0000000..c3b3378 --- /dev/null +++ b/src/test/java/org/gcube/common/authz/GenerateTest.java @@ -0,0 +1,77 @@ +package org.gcube.common.authz; + +import java.util.ArrayList; + +import javax.ws.rs.client.Entity; +import javax.ws.rs.core.Application; + +import org.gcube.common.authorization.library.provider.ContainerInfo; +import org.gcube.common.authorization.library.provider.ServiceIdentifier; +import org.gcube.common.authorization.library.provider.ServiceInfo; +import org.gcube.common.authorization.library.provider.UserInfo; +import org.gcube.common.authorizationservice.TokenManager; +import org.gcube.common.authorizationservice.util.TokenPersistence; +import org.glassfish.hk2.utilities.binding.AbstractBinder; +import org.glassfish.jersey.server.ResourceConfig; +import org.glassfish.jersey.test.JerseyTest; +import org.junit.Assert; +import org.junit.Test; + + +public class GenerateTest extends JerseyTest{ + + @Override + protected Application configure() { + AbstractBinder binder = new AbstractBinder() { + @Override + protected void configure() { + bindFactory(TokenPersistenceFactory.class) + .to(TokenPersistence.class); + } + }; + ResourceConfig config = new ResourceConfig(TokenManager.class); + config.register(binder); + return config; + } + + @Test + public void generateTokenForUser() { + + String token = target("token").path("user").queryParam("context", "/gcube").request().put(Entity.xml(new UserInfo("lucio.lelii", new ArrayList())), String.class); + Assert.assertNotNull(token); + } + + @Test(expected=Exception.class) + public void generateTokenForUserERROR() { + target("token").path("user").queryParam("context", "/gcube").request().put(Entity.xml(new UserInfo("lucio.lelii:pippo", new ArrayList())), String.class); + } + + @Test + public void generateTokenForService() { + String token = target("token").path("service") + .queryParam("context", "/gcube").request().put(Entity.xml(new ServiceInfo(new ServiceIdentifier("Class", "name", "id"))), String.class); + Assert.assertNotNull(token); + } + + @Test(expected=Exception.class) + public void generateTokenForServiceERROR() { + target("token").path("service") + .queryParam("context", "/gcube").request().put(Entity.xml(new ServiceInfo(new ServiceIdentifier("Class:class2", "name", "id"))), String.class); + + } + + @Test + public void generateTokenForNode() { + String token = target("token").path("node") + .queryParam("context", "/gcube").request().put(Entity.xml(new ContainerInfo("node.isti.cnr.it", 8080)), String.class); + Assert.assertNotNull(token); + } + + @Test(expected=Exception.class) + public void generateTokenForNodeERROR() { + target("token").path("node") + .queryParam("context", "/gcube").request().put(Entity.xml(new ServiceInfo(new ServiceIdentifier("Class:class2", "name", "id"))), String.class); + + } + +} diff --git a/src/test/java/org/gcube/common/authz/Importer.java b/src/test/java/org/gcube/common/authz/Importer.java new file mode 100644 index 0000000..1337b4e --- /dev/null +++ b/src/test/java/org/gcube/common/authz/Importer.java @@ -0,0 +1,129 @@ +package org.gcube.common.authz; + +import java.io.StringReader; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import javax.persistence.Persistence; + +import org.gcube.common.authorization.library.provider.UserInfo; +import org.gcube.common.authorizationservice.persistence.RelationDBPersistence; +import org.gcube.common.couchdb.connector.HttpCouchClient; +import org.gcube.common.scope.impl.ScopeBean; +import org.gcube.common.scope.impl.ScopeBean.Type; + +import com.google.gson.Gson; +import com.google.gson.stream.JsonReader; + +public class Importer { + + private static final String URL = "http://accounting-d-d4s.d4science.org/"; + private static final String TEST_DB = "authorization"; + private static final String TEST_USER_USERNAME = "admin"; + private static final String TEST_USER_PASSWORD = "better_than_nothing"; + + private static final String DESIGN_NAME = "_gcube"; + private static final String VIEW_NAME = "_user_and_scope"; + + private static final List usernameToAvoid = Arrays.asList("lucio.lelii", "roberto.cirillo", "luca.frosini", "valentina.marioli", + "massimiliano.assante", "costantino.perciante", "francesco.mangiacrapa", "fabio.sinibaldi", + "giancarlo.panichi", "alessandro.pieve","pasquale.pagano","leonardo.candela", "andrea.rossi"); + + public static void main(String[] args) throws Exception { + HttpCouchClient httpCouch =new HttpCouchClient(URL,TEST_DB, TEST_USER_USERNAME, TEST_USER_PASSWORD); + String docs = httpCouch.getAllDocs(); + + JsonReader reader = new Gson().newJsonReader(new StringReader(docs)); + + ArrayList idList = new ArrayList(); + + reader.beginObject(); + reader.nextName(); + reader.nextInt(); + reader.nextName(); + reader.nextInt(); + reader.nextName(); + reader.beginArray(); + while (reader.hasNext()){ + reader.beginObject(); + reader.nextName(); + String id = reader.nextString(); + idList.add(id); + reader.nextName(); + reader.nextString(); + reader.nextName(); + reader.beginObject(); + reader.nextName(); + reader.nextString(); + reader.endObject(); + reader.endObject(); + } + + reader.close(); + + int tokenToinsert =0; + + RelationDBPersistence rdp = new RelationDBPersistence(); + rdp.setEntitymanagerFactory(Persistence.createEntityManagerFactory("authorization")); + + + for (String id : idList){ + + String doc = httpCouch.getDoc(id); + try{ + + reader = new Gson().newJsonReader(new StringReader(doc)); + reader.beginObject(); + reader.nextName(); + reader.nextString(); + reader.nextName(); + reader.nextString(); + reader.nextName(); + String token = reader.nextString(); + reader.nextName(); + String userName = reader.nextString(); + System.out.println("token = "+token); + System.out.println("username = "+userName); + if (usernameToAvoid.contains(userName)) + throw new Exception("name not to store"); + + //roles + reader.nextName(); + reader.beginArray(); + List roles = new ArrayList(); + while (reader.hasNext()) + roles.add(reader.nextString()); + reader.endArray(); + //end roles + + System.out.println("roles = "+roles.toString()); + + reader.nextName(); + String scope = reader.nextString(); + System.out.println("scope = "+scope); + + if (!new ScopeBean(scope).is(Type.VRE)) + throw new Exception("is not a vre token"); + reader.endObject(); + + try{ + rdp.saveAuthorizationEntry(token, scope, new UserInfo(userName, roles), "TOKEN", "default"); + }catch(Exception e){ + System.out.println(e.getMessage()); + } + tokenToinsert++; + + + }catch (Exception e) { + System.out.println(e.getMessage()+" : "+doc); + }finally{ + reader.close(); + } + } + + System.out.println("token inserted "+tokenToinsert); + + } +} + diff --git a/src/test/java/org/gcube/common/authz/PolicyManagerTest.java b/src/test/java/org/gcube/common/authz/PolicyManagerTest.java new file mode 100644 index 0000000..a9e3447 --- /dev/null +++ b/src/test/java/org/gcube/common/authz/PolicyManagerTest.java @@ -0,0 +1,92 @@ +package org.gcube.common.authz; + +import java.util.ArrayList; +import java.util.List; + +import javax.ws.rs.client.Entity; +import javax.ws.rs.core.Application; +import javax.ws.rs.core.Response; + +import lombok.extern.slf4j.Slf4j; + +import org.gcube.common.authorization.library.Policies; +import org.gcube.common.authorization.library.policies.Action; +import org.gcube.common.authorization.library.policies.Policy; +import org.gcube.common.authorization.library.policies.Service2ServicePolicy; +import org.gcube.common.authorization.library.policies.ServiceAccess; +import org.gcube.common.authorization.library.policies.Services; +import org.gcube.common.authorization.library.policies.User2ServicePolicy; +import org.gcube.common.authorization.library.policies.Users; +import org.gcube.common.authorizationservice.PolicyManager; +import org.gcube.common.authorizationservice.util.TokenPersistence; +import org.glassfish.hk2.utilities.binding.AbstractBinder; +import org.glassfish.jersey.server.ResourceConfig; +import org.glassfish.jersey.test.JerseyTest; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +@Slf4j +public class PolicyManagerTest extends JerseyTest{ + + @Override + protected Application configure() { + AbstractBinder binder = new AbstractBinder() { + @Override + protected void configure() { + bindFactory(TokenPersistenceFactory.class) + .to(TokenPersistence.class); + } + }; + ResourceConfig config = new ResourceConfig(PolicyManager.class); + config.register(binder); + return config; + } + + List policiesList; + + Policies retrievedPolicies; + + @Before + public void reset(){ + retrievedPolicies = null; + policiesList = null; + } + + @Test + public void add() throws Exception{ + log.debug("starting add test"); + policiesList = new ArrayList(); + policiesList.add(new User2ServicePolicy("/gcube", new ServiceAccess(), Users.one("lucio.lelii"), Action.ACCESS)); + policiesList.add(new Service2ServicePolicy("/gcube", new ServiceAccess("SpeciesProductDiscovery", "DataAccess"), Services.specialized(new ServiceAccess("DataAnalysis")), Action.WRITE)); + Response response = target("policyManager").request() + .post(Entity.xml(new Policies(policiesList)), Response.class); + Assert.assertEquals(200, response.getStatus()); + } + + @Test + public void getAllWithAdd() throws Exception{ + add(); + getAll(); + Assert.assertEquals(policiesList.size(), retrievedPolicies.getPolicies().size()); + } + + + private void getAll() throws Exception{ + retrievedPolicies = target("policyManager").queryParam("context", "/gcube").request().get(Policies.class); + log.debug("policyListSize is "+retrievedPolicies.getPolicies().size()); + } + + @Test + public void deleteOne() throws Exception{ + add(); + getAll(); + int sizeBefore = retrievedPolicies.getPolicies().size(); + Policy policy = retrievedPolicies.getPolicies().get(0); + Response response = target("policyManager").path(String.valueOf(policy.getId())).request().delete(Response.class); + Assert.assertEquals(200, response.getStatus()); + getAll(); + Assert.assertEquals(sizeBefore-1, retrievedPolicies.getPolicies().size()); + } + +} diff --git a/src/test/java/org/gcube/common/authz/RetrieveTest.java b/src/test/java/org/gcube/common/authz/RetrieveTest.java new file mode 100644 index 0000000..187aba8 --- /dev/null +++ b/src/test/java/org/gcube/common/authz/RetrieveTest.java @@ -0,0 +1,59 @@ +package org.gcube.common.authz; + +import java.util.Arrays; + +import javax.ws.rs.client.Entity; +import javax.ws.rs.core.Application; + +import lombok.extern.slf4j.Slf4j; + +import org.gcube.common.authorization.library.AuthorizationEntry; +import org.gcube.common.authorization.library.provider.ContainerInfo; +import org.gcube.common.authorization.library.provider.UserInfo; +import org.gcube.common.authorizationservice.TokenManager; +import org.gcube.common.authorizationservice.util.TokenPersistence; +import org.glassfish.hk2.utilities.binding.AbstractBinder; +import org.glassfish.jersey.server.ResourceConfig; +import org.glassfish.jersey.test.JerseyTest; +import org.junit.Assert; +import org.junit.Test; + +@Slf4j +public class RetrieveTest extends JerseyTest{ + + @Override + protected Application configure() { + AbstractBinder binder = new AbstractBinder() { + @Override + protected void configure() { + bindFactory(TokenPersistenceFactory.class) + .to(TokenPersistence.class); + } + }; + ResourceConfig config = new ResourceConfig(TokenManager.class); + config.register(binder); + return config; + } + + @Test + public void generateAndRetrieveToken() throws Exception{ + String token = target("token").path("user").queryParam("context", "/gcube").request().put(Entity.xml(new UserInfo("lucio.lelii", Arrays.asList("Role1", "Role2"))), String.class); + log.info("generated token is "+token); + Assert.assertNotNull(token); + AuthorizationEntry entry = target("token").path(token).request().get(AuthorizationEntry.class); + Assert.assertNotNull(entry); + System.out.println(entry); + } + + + @Test + public void retrieveToken() throws Exception{ + String token = target("token").path("node") + .queryParam("context", "/gcube").request().put(Entity.xml(new ContainerInfo("node.isti.cnr.it", 8080)), String.class); + Assert.assertNotNull(token); + AuthorizationEntry entry = target("token").path(token).request().get(AuthorizationEntry.class); + System.out.println(entry); + } + + +} diff --git a/src/test/java/org/gcube/common/authz/TestPersistence.java b/src/test/java/org/gcube/common/authz/TestPersistence.java new file mode 100644 index 0000000..e3fc0f4 --- /dev/null +++ b/src/test/java/org/gcube/common/authz/TestPersistence.java @@ -0,0 +1,124 @@ +package org.gcube.common.authz; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import javax.persistence.EntityManager; +import javax.persistence.EntityManagerFactory; +import javax.persistence.Persistence; +import javax.persistence.TypedQuery; + +import org.gcube.common.authorization.library.policies.Action; +import org.gcube.common.authorization.library.policies.Roles; +import org.gcube.common.authorization.library.policies.ServiceAccess; +import org.gcube.common.authorization.library.policies.Services; +import org.gcube.common.authorization.library.policies.Users; +import org.gcube.common.authorization.library.provider.UserInfo; +import org.gcube.common.authorizationservice.persistence.entities.AuthorizationEntity; +import org.gcube.common.authorizationservice.persistence.entities.AuthorizationId; +import org.gcube.common.authorizationservice.persistence.entities.ServiceAuthorizationEntity; +import org.gcube.common.authorizationservice.persistence.entities.ServicePolicyEntity; +import org.gcube.common.authorizationservice.persistence.entities.UserAuthorizationEntity; +import org.gcube.common.authorizationservice.persistence.entities.UserPolicyEntity; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; + +public class TestPersistence { + + private static EntityManagerFactory mEmf; + + private static EntityManager mEntityManager; + + @BeforeClass + public static void before(){ + try{ + mEmf = Persistence.createEntityManagerFactory("TestPersistence"); + mEntityManager = mEmf.createEntityManager(); + }catch(Exception e){ + e.printStackTrace(); + throw e; + } + } + + @Test + public void testAuthorizationEntities(){ + + AuthorizationEntity entity = mEntityManager.find(AuthorizationEntity.class, new AuthorizationId("/gcube", "lucio.lelii", "JavaClient")); + + try{ + if (entity==null){ + mEntityManager.getTransaction().begin(); + mEntityManager.persist(new UserAuthorizationEntity("token", "/gcube", "JavaClient", new UserInfo("lucio.lelii", new ArrayList()))); + mEntityManager.getTransaction().commit(); + } + }catch(Exception e){ + e.printStackTrace(); + throw e; + } + + AuthorizationEntity entity2 = mEntityManager.find(AuthorizationEntity.class, new AuthorizationId("/gcube", "lucio.lelii", "JavaClient")); + + + System.out.println(entity2); + + TypedQuery query = mEntityManager.createNamedQuery("User.get", UserAuthorizationEntity.class); + query.setParameter("token", "token"); + query.setParameter("context", "/gcube"); + query.setParameter("clientId", "lucio.lelii"); + List descriptors = query.getResultList(); + Assert.assertTrue(descriptors.size()==1); + + TypedQuery queryS = mEntityManager.createNamedQuery("Service.get", ServiceAuthorizationEntity.class); + queryS.setParameter("token", "token2"); + queryS.setParameter("context", "/gcube"); + queryS.setParameter("clientId", "class:name:id"); + List descriptorsS = queryS.getResultList(); + Assert.assertTrue(descriptorsS.size()==0); + } + + @Test + public void testPolicyEntities(){ + + try{ + mEntityManager.getTransaction().begin(); + mEntityManager.persist(new UserPolicyEntity("/gcube", new ServiceAccess(), Roles.allExcept("VOManager"), Action.ALL)); + mEntityManager.persist(new UserPolicyEntity("/gcube", new ServiceAccess("DataAnalysis"), Users.one("lucio.lelii"), Action.ALL)); + mEntityManager.persist(new ServicePolicyEntity("/gcube", new ServiceAccess("DataAnalysis"), Services.specialized(new ServiceAccess("TabularData","DataAnalysis")), Action.ALL)); + mEntityManager.persist(new ServicePolicyEntity("/gcube", new ServiceAccess("DataAnalysis"), Services.specialized(new ServiceAccess("DataAccess")), Action.ALL)); + mEntityManager.persist(new ServicePolicyEntity("/gcube", new ServiceAccess("DataAnalysis"), Services.allExcept(new ServiceAccess("DataAnalysis")), Action.ALL)); + mEntityManager.persist(new ServicePolicyEntity("/gcube", new ServiceAccess("DataAnalysis"), Services.all(), Action.ALL)); + mEntityManager.getTransaction().commit(); + }catch(Exception e){ + e.printStackTrace(); + throw e; + } + + TypedQuery query = mEntityManager.createNamedQuery("UserPolicy.get", UserPolicyEntity.class); + query.setParameter("context", "/gcube"); + query.setParameter("user", "pippo.lelii"); + query.setParameter("rolesList", Collections.singleton("")); + List descriptors = query.getResultList(); + Assert.assertTrue(descriptors.size()==1); + + TypedQuery queryS = mEntityManager.createNamedQuery("ServicePolicy.get", ServicePolicyEntity.class); + queryS.setParameter("context", "/gcube"); + queryS.setParameter("serviceClass", "DataAccess"); + queryS.setParameter("serviceName", "Species"); + queryS.setParameter("identifier", "Id"); + + List descriptorsS = queryS.getResultList(); + System.out.println(descriptorsS); + Assert.assertTrue(descriptorsS.size()==3); + } + + @AfterClass + public static void after(){ + mEntityManager.close(); + mEmf.close(); + } + + +} diff --git a/src/test/java/org/gcube/common/authz/TokenPersistenceFactory.java b/src/test/java/org/gcube/common/authz/TokenPersistenceFactory.java new file mode 100644 index 0000000..8b83fa7 --- /dev/null +++ b/src/test/java/org/gcube/common/authz/TokenPersistenceFactory.java @@ -0,0 +1,23 @@ +package org.gcube.common.authz; + +import javax.persistence.Persistence; + +import org.gcube.common.authorizationservice.persistence.RelationDBPersistence; +import org.gcube.common.authorizationservice.util.TokenPersistence; +import org.glassfish.hk2.api.Factory; + +public class TokenPersistenceFactory implements Factory { + + @Override + public void dispose(TokenPersistence arg0) { + } + + @Override + public TokenPersistence provide() { + RelationDBPersistence rdbp = new RelationDBPersistence(); + rdbp.setEntitymanagerFactory(Persistence.createEntityManagerFactory("TestPersistence")); + return rdbp; + + } + +} diff --git a/src/test/java/org/gcube/common/authz/configuration/Binder.java b/src/test/java/org/gcube/common/authz/configuration/Binder.java new file mode 100644 index 0000000..252552c --- /dev/null +++ b/src/test/java/org/gcube/common/authz/configuration/Binder.java @@ -0,0 +1,69 @@ +package org.gcube.common.authz.configuration; + +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.io.StringReader; +import java.io.StringWriter; + +import javax.xml.bind.JAXBContext; + +import org.gcube.common.authorizationservice.configuration.AllowedEntity; +import org.gcube.common.authorizationservice.configuration.AllowedEntity.EntityType; +import org.gcube.common.authorizationservice.configuration.AuthorizationConfiguration; +import org.gcube.common.authorizationservice.configuration.AuthorizationRule; +import org.gcube.common.authorizationservice.configuration.ConfigurationBuilder; +import org.gcube.common.authorizationservice.configuration.RuleBuilder; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; + +public class Binder { + + private static JAXBContext context; + + @BeforeClass + public static void init() throws Exception{ + context = JAXBContext.newInstance(AuthorizationConfiguration.class); + } + + @Test + public void binder() throws Exception{ + AuthorizationRule firtRule = new RuleBuilder().path("/*").entity(new AllowedEntity(EntityType.IP, "192.168.0.1")).entity(new AllowedEntity(EntityType.IP, "192.168.0.2")).build(); + AuthorizationRule secondRule = new RuleBuilder().path("/newPath").entity(new AllowedEntity(EntityType.ROLE, "ContextManager")).entity(new AllowedEntity(EntityType.IP, "192.168.0.3")).build(); + AuthorizationRule thirdRule = new RuleBuilder().path("/anotherPath").entity(new AllowedEntity(EntityType.USER, "user")).build(); + + AuthorizationConfiguration authConf = ConfigurationBuilder.getBuilder().rule(firtRule).rule(secondRule).rule(thirdRule).build(); + StringWriter sw = new StringWriter(); + context.createMarshaller().marshal(authConf, sw); + System.out.println(sw); + AuthorizationConfiguration extractedRule = (AuthorizationConfiguration)context.createUnmarshaller().unmarshal(new StringReader(sw.toString())); + System.out.println(extractedRule); + + Assert.assertTrue(authConf.equals(extractedRule)); + } + + @Test + public void loadBinder() throws Exception{ + + try( BufferedReader reader = new BufferedReader(new InputStreamReader(ClassLoader.getSystemClassLoader().getResourceAsStream("AuthorizationConfiguration.xml")))){ + String line = null; + while ((line=reader.readLine())!=null) + System.out.println(line); + } + + + AuthorizationConfiguration authConf = (AuthorizationConfiguration)context.createUnmarshaller().unmarshal( + new BufferedReader(new InputStreamReader(ClassLoader.getSystemClassLoader().getResourceAsStream("AuthorizationConfiguration.xml")))); + System.out.println(authConf); + + StringWriter sw = new StringWriter(); + context.createMarshaller().marshal(authConf, sw); + System.out.println(sw); + AuthorizationConfiguration extractedRule = (AuthorizationConfiguration)context.createUnmarshaller().unmarshal(new StringReader(sw.toString())); + Assert.assertTrue(authConf.equals(extractedRule)); + + } + + + +} diff --git a/src/test/resources/AuthorizationConfiguration.xml b/src/test/resources/AuthorizationConfiguration.xml new file mode 100644 index 0000000..67752f6 --- /dev/null +++ b/src/test/resources/AuthorizationConfiguration.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/src/test/resources/META-INF/beans.xml b/src/test/resources/META-INF/beans.xml new file mode 100644 index 0000000..5cfb427 --- /dev/null +++ b/src/test/resources/META-INF/beans.xml @@ -0,0 +1,8 @@ + + + org.gcube.common.authorizationservice.persistence.DataBaseProducer + + \ No newline at end of file diff --git a/src/test/resources/META-INF/persistence.xml b/src/test/resources/META-INF/persistence.xml new file mode 100644 index 0000000..cd38c2b --- /dev/null +++ b/src/test/resources/META-INF/persistence.xml @@ -0,0 +1,35 @@ + + + + + org.eclipse.persistence.jpa.PersistenceProvider + + + org.gcube.common.authorizationservice.persistence.entities.converters.StringListConverter + + + org.gcube.common.authorizationservice.persistence.entities.AuthorizationEntity + org.gcube.common.authorizationservice.persistence.entities.ServiceAuthorizationEntity + org.gcube.common.authorizationservice.persistence.entities.UserAuthorizationEntity + org.gcube.common.authorizationservice.persistence.entities.ExternalServiceAuthorizationEntity + org.gcube.common.authorizationservice.persistence.entities.NodeAuthorizationEntity + org.gcube.common.authorizationservice.persistence.entities.PolicyEntity + org.gcube.common.authorizationservice.persistence.entities.ServicePolicyEntity + org.gcube.common.authorizationservice.persistence.entities.UserPolicyEntity + + + + + + + + + + + + + \ No newline at end of file