request for bunch token creation for service and container added

This commit is contained in:
lucio 2019-12-09 18:06:21 +01:00
parent d7ba58155f
commit f71693619e
12 changed files with 187 additions and 46 deletions

View File

@ -24,16 +24,16 @@
<attribute name="test" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
<attributes>
<attribute name="maven.pomderived" value="true"/>
<attribute name="org.eclipse.jst.component.dependency" value="/WEB-INF/lib"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="output" path="target/classes"/>
</classpath>

View File

@ -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

View File

@ -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

36
pom.xml
View File

@ -1,4 +1,5 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
@ -19,48 +20,60 @@
<distroDirectory>distro</distroDirectory>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.gcube.distribution</groupId>
<artifactId>gcube-bom</artifactId>
<version>1.3.1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.gcube.common</groupId>
<artifactId>common-authorization</artifactId>
<version>[2.0.0-SNAPSHOT, 3.0.0-SNAPSHOT)</version>
</dependency>
<dependency>
<groupId>org.gcube.core</groupId>
<artifactId>common-encryption</artifactId>
<version>[1.0.0-SNAPSHOT, 2.0.0-SNAPSHOT)</version>
</dependency>
<dependency>
<groupId>org.gcube.data.publishing</groupId>
<artifactId>document-store-lib</artifactId>
</dependency>
<dependency>
<groupId>org.gcube.accounting</groupId>
<artifactId>accounting-lib</artifactId>
</dependency>
<dependency>
<groupId>org.gcube.core</groupId>
<artifactId>common-scope-maps</artifactId>
<version>[1.0.0-SNAPSHOT,2.0.0-SNAPSHOT)</version>
</dependency>
<dependency>
<groupId>org.gcube.core</groupId>
<artifactId>common-scope</artifactId>
<version>[1.0.0-SNAPSHOT,2.0.0-SNAPSHOT)</version>
</dependency>
<dependency>
<groupId>org.gcube.core</groupId>
<artifactId>common-encryption</artifactId>
<version>[1.0.0-SNAPSHOT, 2.0.0-SNAPSHOT)</version>
</dependency>
<!-- jersey -->
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>javax.ws.rs-api</artifactId>
<version>2.0</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet</artifactId>
<version>2.13</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers.glassfish</groupId>
@ -165,11 +178,6 @@
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>

View File

@ -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);

View File

@ -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<String> tokens ) {
CalledMethodProvider.instance.set("retrieve");
log.info("token retreiver called with token {}",tokens);
List<AuthorizationEntry> toReturn = new ArrayList<AuthorizationEntry>();
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<String> tokensToReturn = new ArrayList<String>();
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);

View File

@ -19,6 +19,9 @@ public class AuthorizationConfiguration {
@XmlElement(name="AllowedContainerIp")
private List<String> allowedContainerIps = new ArrayList<String>();
@XmlElement(name="AccountingDir")
private String accountingDir = "/tmp";
protected AuthorizationConfiguration(){}
public List<AuthorizationRule> getAuthorizationRules() {
@ -28,6 +31,14 @@ public class AuthorizationConfiguration {
protected void setAuthorizationRules(List<AuthorizationRule> rules) {
this.authorizationRules = rules;
}
public String getAccountingDir() {
return accountingDir;
}
protected void setAccountingDir(String accountingDir) {
this.accountingDir = accountingDir;
}
public List<String> getAllowedContainerIps() {
return allowedContainerIps;

View File

@ -9,7 +9,9 @@ public class ConfigurationBuilder {
List<AuthorizationRule> rules = new ArrayList<AuthorizationRule>();
List<String> ips = new ArrayList<String>();
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;
}

View File

@ -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);
}
}
}

View File

@ -6,4 +6,5 @@
<Rule path="/token/external" requiresToken="true" acceptedTokenTypes="USER" />
<Rule path="/token/node" requiresToken="false" />
<Rule path="/token/service" requiresToken="true" acceptedTokenTypes="CONTAINER"/>
<AccountingDir>/tmp</AccountingDir>
</Configuration>

View File

@ -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);

View File

@ -6,5 +6,6 @@
<Rule path="/apikey" requiresToken="true"/>
<Rule path="/policyManager" requiresToken="true"/>
<Rule path="/token/external" requiresToken="true"/>
<AccountingDir>mydir</AccountingDir>
</Configuration>