diff --git a/.classpath b/.classpath
index 63c80a6..11def0e 100644
--- a/.classpath
+++ b/.classpath
@@ -24,16 +24,16 @@
-
-
-
-
-
+
+
+
+
+
diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs
index 8db228c..4e4a3ad 100644
--- a/.settings/org.eclipse.jdt.core.prefs
+++ b/.settings/org.eclipse.jdt.core.prefs
@@ -1,9 +1,9 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
-org.eclipse.jdt.core.compiler.compliance=1.7
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
+org.eclipse.jdt.core.compiler.compliance=1.8
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
org.eclipse.jdt.core.compiler.release=disabled
-org.eclipse.jdt.core.compiler.source=1.7
+org.eclipse.jdt.core.compiler.source=1.8
diff --git a/README.md b/README.md
index b8eefc8..ec907f1 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-# Storage Hub Webapp
+# Authorization service
StorageHub implements the gCube Workspace feature
@@ -13,11 +13,11 @@ StorageHub implements the gCube Workspace feature
## Documentation
-* Use of this theme is described in the [Wiki](https://wiki.gcube-system.org/gcube/StorageHub_REST_API).
+* Use of this theme is described in the [Wiki](https://wiki.gcube-system.org/gcube/Authorization_Framework).
## Change log
-See [Releases](https://code-repo.d4science.org/gCubeSystem/storagehub/releases).
+See [Releases](https://code-repo.d4science.org/gCubeSystem/authorization-service/releases).
## Authors
diff --git a/pom.xml b/pom.xml
index ac99d20..46bb61b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1,4 +1,5 @@
-
4.0.0
@@ -19,48 +20,60 @@
distro
+
+
+
+ org.gcube.distribution
+ gcube-bom
+ 1.3.1
+ pom
+ import
+
+
+
+
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.data.publishing
+ document-store-lib
+
+
+ org.gcube.accounting
+ accounting-lib
+
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
@@ -165,11 +178,6 @@
maven-compiler-plugin
- 2.3.2
-
-
- 1.7
-
org.apache.maven.plugins
diff --git a/src/main/java/org/gcube/common/authorizationservice/ApiKeyManager.java b/src/main/java/org/gcube/common/authorizationservice/ApiKeyManager.java
index 405acf4..64b09cb 100644
--- a/src/main/java/org/gcube/common/authorizationservice/ApiKeyManager.java
+++ b/src/main/java/org/gcube/common/authorizationservice/ApiKeyManager.java
@@ -21,6 +21,7 @@ import lombok.extern.slf4j.Slf4j;
import org.gcube.common.authorization.library.AuthorizationEntry;
import org.gcube.common.authorization.library.QualifiersList;
+import org.gcube.common.authorization.library.provider.CalledMethodProvider;
import org.gcube.common.authorizationservice.filters.AuthorizedCallFilter;
import org.gcube.common.authorizationservice.util.Constants;
import org.gcube.common.authorizationservice.util.TokenPersistence;
@@ -43,6 +44,7 @@ public class ApiKeyManager {
@PUT
@Consumes(MediaType.APPLICATION_XML)
public String generateApiKey(@QueryParam(value="qualifier")String qualifier, @Context HttpServletRequest req) {
+ CalledMethodProvider.instance.set("generate(APIKEY)");
try{
AuthorizationEntry info = (AuthorizationEntry)req.getAttribute(AuthorizedCallFilter.AUTH_ATTRIBUTE);
@@ -79,6 +81,7 @@ public class ApiKeyManager {
@GET
@Produces(MediaType.APPLICATION_XML)
public QualifiersList retrieveApiKeys(@Context HttpServletRequest req) {
+ CalledMethodProvider.instance.set("retrieve(APIKEY)");
log.info("calling getApiKey");
try{
AuthorizationEntry info = (AuthorizationEntry)req.getAttribute(AuthorizedCallFilter.AUTH_ATTRIBUTE);
diff --git a/src/main/java/org/gcube/common/authorizationservice/TokenManager.java b/src/main/java/org/gcube/common/authorizationservice/TokenManager.java
index d0d497b..57327de 100644
--- a/src/main/java/org/gcube/common/authorizationservice/TokenManager.java
+++ b/src/main/java/org/gcube/common/authorizationservice/TokenManager.java
@@ -1,12 +1,10 @@
package org.gcube.common.authorizationservice;
-import java.util.HashMap;
+import java.util.ArrayList;
import java.util.List;
-import java.util.Map;
import java.util.UUID;
import javax.inject.Inject;
-import javax.print.attribute.HashAttributeSet;
import javax.servlet.http.HttpServletRequest;
import javax.validation.constraints.NotNull;
import javax.ws.rs.Consumes;
@@ -22,20 +20,22 @@ 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.ExternalServiceList;
+import org.gcube.common.authorization.library.provider.CalledMethodProvider;
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.authorization.library.utils.AuthorizationEntryList;
import org.gcube.common.authorization.library.utils.ListMapper;
+import org.gcube.common.authorization.library.utils.MapAdapter;
+import org.gcube.common.authorization.library.utils.MultiServiceTokenRequest;
import org.gcube.common.authorizationservice.filters.AuthorizedCallFilter;
import org.gcube.common.authorizationservice.util.Constants;
import org.gcube.common.authorizationservice.util.TokenPersistence;
-import org.gcube.common.scope.api.ScopeProvider;
-import org.gcube.common.scope.api.ServiceMap;
+
+import lombok.extern.slf4j.Slf4j;
@Path("token")
@Slf4j
@@ -56,7 +56,7 @@ public class TokenManager {
@Path("{token}")
@Produces(MediaType.APPLICATION_XML)
public AuthorizationEntry retrieveToken(@NotNull @PathParam("token") String token ) {
-
+ CalledMethodProvider.instance.set("retieve");
log.info("token retreiver called with token {}",token);
AuthorizationEntry info = persistence.getAuthorizationEntry(token);
@@ -87,6 +87,36 @@ public class TokenManager {
}
+ /**
+ *
+ * retrieves the AuthorzationEntry connected to the specified token
+ *
+ * @param token
+ * @return the authorization entry
+ */
+ @GET
+ @Path("resolve")
+ @Produces(MediaType.APPLICATION_XML)
+ public AuthorizationEntryList retrieveTokenBunch(@NotNull @QueryParam("token") List tokens ) {
+ CalledMethodProvider.instance.set("retrieve");
+ log.info("token retreiver called with token {}",tokens);
+
+ List toReturn = new ArrayList();
+ for (String token : tokens ) {
+ AuthorizationEntry info = persistence.getAuthorizationEntry(token);
+ if (token!=null) toReturn.add(info);
+ }
+ log.info("info retrieved {}",toReturn);
+
+ if (toReturn.isEmpty()){
+ log.error("no tokens poassed have been found ");
+ throw new WebApplicationException(Response.status(Response.Status.NOT_FOUND)
+ .entity("no tokens poassed have been found ").type(MediaType.TEXT_PLAIN).build());
+ }
+
+ return new AuthorizationEntryList(toReturn);
+
+ }
@@ -100,7 +130,7 @@ public class TokenManager {
@GET
@Path("resolve/{user}")
public String getTokenByUserAndContext(@NotNull @PathParam("user") String user, @QueryParam("context") String context ) {
-
+ CalledMethodProvider.instance.set("retrieve");
log.info("resolving token for user {} in context {}",user, context);
if (context==null){
@@ -146,7 +176,7 @@ public class TokenManager {
@Consumes(MediaType.APPLICATION_XML)
public String generateUserToken(UserInfo clientId,
@NotNull @QueryParam("context") String context) {
-
+ CalledMethodProvider.instance.set("generate");
try{
log.info("generator called with user {} in context {} ",clientId, context);
@@ -181,7 +211,7 @@ public class TokenManager {
@Consumes(MediaType.APPLICATION_XML)
public String setRoles(ListMapper roles,
@NotNull @PathParam("token") String token) {
-
+ CalledMethodProvider.instance.set("setRoles");
try{
log.info("update roles called");
@@ -210,7 +240,7 @@ public class TokenManager {
@Consumes(MediaType.APPLICATION_XML)
public void removeUserToken(@NotNull @QueryParam("client_id") String clientId,
@NotNull @QueryParam("context") String context) {
-
+ CalledMethodProvider.instance.set("delete");
try{
log.info("generator called with user {} in context {} ",clientId, context);
@@ -239,6 +269,7 @@ public class TokenManager {
@Consumes(MediaType.APPLICATION_XML)
public String generateServiceToken(ServiceInfo serviceInfo,
@Context HttpServletRequest req) {
+ CalledMethodProvider.instance.set("generate");
try{
AuthorizationEntry authInfo = (AuthorizationEntry)req.getAttribute(AuthorizedCallFilter.AUTH_ATTRIBUTE);
log.info("generator called with service {} in context {} ",serviceInfo.getId(), authInfo.getContext());
@@ -251,7 +282,46 @@ public class TokenManager {
}
-
+ /**
+ *
+ * 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/bunch")
+ @PUT
+ @Consumes(MediaType.APPLICATION_XML)
+ public ListMapper generateServiceTokenBunch(MultiServiceTokenRequest entity,
+ @Context HttpServletRequest req) {
+ CalledMethodProvider.instance.set("generate");
+
+ try{
+
+ AuthorizationEntry callerInfo = (AuthorizationEntry)req.getAttribute(AuthorizedCallFilter.AUTH_ATTRIBUTE);
+
+ List tokensToReturn = new ArrayList();
+
+ for (String token: entity.getContainerTokens()) {
+ AuthorizationEntry authInfo = this.retrieveToken(token);
+
+ if (!authInfo.getClientInfo().getId().equals(callerInfo.getClientInfo().getId()))
+ log.warn("a token with a different ContainerInfo of the caller used, skipping it");
+ else {
+ String genToken = generateTokenForServiceInfo(entity.getInfo(), authInfo);
+ tokensToReturn.add(genToken);
+ }
+
+ }
+
+ return new ListMapper(tokensToReturn);
+ }catch(Exception e){
+ log.error("error generating tokens ",e);
+ throw new WebApplicationException(Response.status(Response.Status.BAD_REQUEST)
+ .entity("Error Generating Token: "+e.getMessage()).type(MediaType.TEXT_PLAIN).build());
+ }
+ }
/**
*
@@ -265,6 +335,7 @@ public class TokenManager {
@Consumes(MediaType.APPLICATION_XML)
public String generateExternalServiceToken(@PathParam("serviceId") String serviceId, @Context HttpServletRequest req) {
try{
+ CalledMethodProvider.instance.set("generate");
AuthorizationEntry info = (AuthorizationEntry)req.getAttribute(AuthorizedCallFilter.AUTH_ATTRIBUTE);
log.info("generator called for external service {} in context {} ",serviceId, info.getContext());
@@ -296,6 +367,7 @@ public class TokenManager {
@GET
@Consumes(MediaType.APPLICATION_XML)
public ExternalServiceList getExternalServiceCreated(@Context HttpServletRequest req) {
+ CalledMethodProvider.instance.set("retrieve");
try{
AuthorizationEntry info = (AuthorizationEntry)req.getAttribute(AuthorizedCallFilter.AUTH_ATTRIBUTE);
log.info("get External Service called in context {} by {} ",info.getContext(), info.getClientInfo().getId());
@@ -313,6 +385,7 @@ public class TokenManager {
@Consumes(MediaType.APPLICATION_XML)
public String generateContainerToken(@NotNull ContainerInfo containerInfo, @QueryParam("context") String context,
@Context HttpServletRequest req) {
+ CalledMethodProvider.instance.set("generate");
try{
AuthorizationEntry info = (AuthorizationEntry)req.getAttribute(AuthorizedCallFilter.AUTH_ATTRIBUTE);
diff --git a/src/main/java/org/gcube/common/authorizationservice/configuration/AuthorizationConfiguration.java b/src/main/java/org/gcube/common/authorizationservice/configuration/AuthorizationConfiguration.java
index a2e75d6..a2cdcaf 100644
--- a/src/main/java/org/gcube/common/authorizationservice/configuration/AuthorizationConfiguration.java
+++ b/src/main/java/org/gcube/common/authorizationservice/configuration/AuthorizationConfiguration.java
@@ -19,6 +19,9 @@ public class AuthorizationConfiguration {
@XmlElement(name="AllowedContainerIp")
private List allowedContainerIps = new ArrayList();
+ @XmlElement(name="AccountingDir")
+ private String accountingDir = "/tmp";
+
protected AuthorizationConfiguration(){}
public List getAuthorizationRules() {
@@ -28,6 +31,14 @@ public class AuthorizationConfiguration {
protected void setAuthorizationRules(List rules) {
this.authorizationRules = rules;
}
+
+ public String getAccountingDir() {
+ return accountingDir;
+ }
+
+ protected void setAccountingDir(String accountingDir) {
+ this.accountingDir = accountingDir;
+ }
public List getAllowedContainerIps() {
return allowedContainerIps;
diff --git a/src/main/java/org/gcube/common/authorizationservice/configuration/ConfigurationBuilder.java b/src/main/java/org/gcube/common/authorizationservice/configuration/ConfigurationBuilder.java
index 4be30b2..c552ad4 100644
--- a/src/main/java/org/gcube/common/authorizationservice/configuration/ConfigurationBuilder.java
+++ b/src/main/java/org/gcube/common/authorizationservice/configuration/ConfigurationBuilder.java
@@ -9,7 +9,9 @@ public class ConfigurationBuilder {
List rules = new ArrayList();
List ips = new ArrayList();
-
+
+ String accountingDir = null;
+
public static ConfigurationBuilder getBuilder(){
return new ConfigurationBuilder();
}
@@ -19,6 +21,11 @@ public class ConfigurationBuilder {
return this;
}
+ public ConfigurationBuilder accountingDir(String accountingDir){
+ this.accountingDir= accountingDir;
+ return this;
+ }
+
public ConfigurationBuilder autoConfirmedIp(String ip){
this.ips.add(ip);
return this;
@@ -28,6 +35,7 @@ public class ConfigurationBuilder {
AuthorizationConfiguration configuration = new AuthorizationConfiguration();
configuration.setAuthorizationRules(rules);
configuration.setAllowedContainerIps(ips);
+ if (accountingDir!=null) configuration.setAccountingDir(accountingDir);
return configuration;
}
diff --git a/src/main/java/org/gcube/common/authorizationservice/filters/AuthorizedCallFilter.java b/src/main/java/org/gcube/common/authorizationservice/filters/AuthorizedCallFilter.java
index 2e9d4d7..5d6ddcb 100644
--- a/src/main/java/org/gcube/common/authorizationservice/filters/AuthorizedCallFilter.java
+++ b/src/main/java/org/gcube/common/authorizationservice/filters/AuthorizedCallFilter.java
@@ -15,14 +15,22 @@ import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
-import lombok.extern.slf4j.Slf4j;
-
+import org.gcube.accounting.datamodel.UsageRecord.OperationResult;
+import org.gcube.accounting.datamodel.usagerecords.ServiceUsageRecord;
+import org.gcube.accounting.persistence.AccountingPersistence;
+import org.gcube.accounting.persistence.AccountingPersistenceFactory;
import org.gcube.common.authorization.library.AuthorizationEntry;
+import org.gcube.common.authorization.library.provider.CalledMethodProvider;
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;
+import org.gcube.common.scope.api.ScopeProvider;
+import org.jboss.weld.context.ApplicationContext;
+import org.omg.PortableInterceptor.SUCCESSFUL;
+
+import lombok.extern.slf4j.Slf4j;
@WebFilter(urlPatterns={"/*"}, filterName="authorizationFilter")
@Slf4j
@@ -41,12 +49,14 @@ public class AuthorizedCallFilter implements Filter {
}
@Override
- public void doFilter(ServletRequest request, ServletResponse response,
- FilterChain chain) throws IOException, ServletException {
+ 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);
-
+
+ long startTime = System.currentTimeMillis();
+
AuthorizationEntry info = null;
if (token!=null){
info = persistence.getAuthorizationEntry(token);
@@ -91,6 +101,8 @@ public class AuthorizedCallFilter implements Filter {
}
chain.doFilter(request, response);
+
+ generateAccounting("Unknown", "Unknown", callerIp, true, startTime, request.getLocalName());
}
private boolean requiresToken(String pathInfo) {
@@ -163,6 +175,30 @@ public class AuthorizedCallFilter implements Filter {
@Override
public void destroy() {}
-
+
+ void generateAccounting(String caller, String callerQualifier, String remoteHost, boolean success, long startTime, String host){
+ AuthorizationConfiguration conf = ConfigurationHolder.getConfiguration();
+ AccountingPersistenceFactory.setFallbackLocation(conf.getAccountingDir());
+ AccountingPersistence persistence = AccountingPersistenceFactory.getPersistence();
+ ServiceUsageRecord serviceUsageRecord = new ServiceUsageRecord();
+ try{
+
+ serviceUsageRecord.setConsumerId(caller);
+ serviceUsageRecord.setCallerQualifier(callerQualifier);
+ serviceUsageRecord.setScope(ScopeProvider.instance.get());
+ serviceUsageRecord.setServiceClass("Common");
+ serviceUsageRecord.setServiceName("Authorization");
+
+ serviceUsageRecord.setHost(host);
+ serviceUsageRecord.setCalledMethod(CalledMethodProvider.instance.get());
+ serviceUsageRecord.setCallerHost(remoteHost);
+ serviceUsageRecord.setOperationResult(success?OperationResult.SUCCESS:OperationResult.FAILED);
+ serviceUsageRecord.setDuration(System.currentTimeMillis()-startTime);
+ persistence.account(serviceUsageRecord);
+
+ }catch(Exception ex){
+ log.warn("invalid record passed to accounting ",ex);
+ }
+ }
}
diff --git a/src/main/webapp/WEB-INF/AuthorizationConfiguration.xml b/src/main/webapp/WEB-INF/AuthorizationConfiguration.xml
index 0e31a43..5ec0512 100644
--- a/src/main/webapp/WEB-INF/AuthorizationConfiguration.xml
+++ b/src/main/webapp/WEB-INF/AuthorizationConfiguration.xml
@@ -6,4 +6,5 @@
+ /tmp
diff --git a/src/test/java/org/gcube/common/authz/configuration/Binder.java b/src/test/java/org/gcube/common/authz/configuration/Binder.java
index deb6d58..f191ac1 100644
--- a/src/test/java/org/gcube/common/authz/configuration/Binder.java
+++ b/src/test/java/org/gcube/common/authz/configuration/Binder.java
@@ -33,7 +33,7 @@ public class Binder {
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();
+ AuthorizationConfiguration authConf = ConfigurationBuilder.getBuilder().rule(firtRule).rule(secondRule).rule(thirdRule).accountingDir("mydir").build();
StringWriter sw = new StringWriter();
context.createMarshaller().marshal(authConf, sw);
System.out.println(sw);
diff --git a/src/test/resources/AuthorizationConfiguration.xml b/src/test/resources/AuthorizationConfiguration.xml
index 67752f6..5c94e2a 100644
--- a/src/test/resources/AuthorizationConfiguration.xml
+++ b/src/test/resources/AuthorizationConfiguration.xml
@@ -6,5 +6,6 @@
+ mydir