commit for new IAM release

This commit is contained in:
Lucio Lelii 2020-11-18 18:50:49 +01:00
parent 441baf14b3
commit a4462eb325
7 changed files with 136 additions and 48 deletions

View File

@ -11,7 +11,7 @@
<groupId>org.gcube.core</groupId>
<artifactId>common-smartgears</artifactId>
<version>2.2.0</version>
<version>2.3.0-SNAPSHOT</version>
<name>SmartGears</name>
<dependencyManagement>
@ -41,6 +41,12 @@
<dependencies>
<dependency>
<groupId>com.eclipsesource.minimal-json</groupId>
<artifactId>minimal-json</artifactId>
<version>0.9.4</version>
</dependency>
<dependency>
<groupId>org.gcube.common</groupId>
<artifactId>authorization-client</artifactId>
@ -165,7 +171,6 @@
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
<scope>runtime</scope>
</dependency>

View File

@ -8,5 +8,6 @@ package org.gcube.smartgears.configuration;
*/
public enum Mode {
online,
offline
offline,
root
}

View File

@ -12,6 +12,7 @@ import org.gcube.common.authorization.client.proxy.AuthorizationProxy;
import org.gcube.common.authorization.library.provider.SecurityTokenProvider;
import org.gcube.common.resources.gcore.GCoreEndpoint;
import org.gcube.informationsystem.publisher.ScopedPublisher;
import org.gcube.smartgears.configuration.Mode;
import org.gcube.smartgears.context.application.ApplicationContext;
import org.gcube.smartgears.provider.ProviderFactory;
import org.slf4j.Logger;
@ -78,21 +79,23 @@ public class ProfilePublisher {
SecurityTokenProvider.instance.set(previousToken);
}
*/
ClassLoader contextCL = Thread.currentThread().getContextClassLoader();
log.debug("using context {}",contextCL.getClass().getSimpleName());
String previousToken = SecurityTokenProvider.instance.get();
try{//This classloader set is needed for the jaxb context
if (previousToken==null)
SecurityTokenProvider.instance.set((String)tokens.toArray()[0]);
Thread.currentThread().setContextClassLoader(ProfilePublisher.class.getClassLoader());
if (context.container().configuration().mode()!=Mode.root) Thread.currentThread().setContextClassLoader(ProfilePublisher.class.getClassLoader());
profile = publisher.create(profile, resolveScopesFromTokens(tokens));
} catch (Exception e) {
rethrowUnchecked(e);
} finally{
SecurityTokenProvider.instance.set(previousToken);
Thread.currentThread().setContextClassLoader(contextCL);
if (context.container().configuration().mode()!=Mode.root) Thread.currentThread().setContextClassLoader(contextCL);
}
sharePublished(profile);
@ -129,19 +132,23 @@ public class ProfilePublisher {
ClassLoader contextCL = Thread.currentThread().getContextClassLoader();
log.debug("using context {}",contextCL.getClass().getSimpleName());
String previousToken = SecurityTokenProvider.instance.get();
try{//This classloader set is needed for the jaxb context
if (previousToken==null)
SecurityTokenProvider.instance.set((String)context.configuration().startTokens().toArray()[0]);
Thread.currentThread().setContextClassLoader(ProfilePublisher.class.getClassLoader());
if (context.container().configuration().mode()!=Mode.root)
Thread.currentThread().setContextClassLoader(ProfilePublisher.class.getClassLoader());
profile = publisher.update(profile);
} catch (Exception e) {
rethrowUnchecked(e);
} finally{
SecurityTokenProvider.instance.set(previousToken);
Thread.currentThread().setContextClassLoader(contextCL);
if (context.container().configuration().mode()!=Mode.root)
Thread.currentThread().setContextClassLoader(contextCL);
}
sharePublished(profile);
@ -178,18 +185,22 @@ public class ProfilePublisher {
ClassLoader contextCL = Thread.currentThread().getContextClassLoader();
log.debug("using context {}",contextCL.getClass().getSimpleName());
String previousToken = SecurityTokenProvider.instance.get();
try{//This classloader set is needed for the jaxb context
if (previousToken==null)
SecurityTokenProvider.instance.set((String)tokens.toArray()[0]);
Thread.currentThread().setContextClassLoader(ProfilePublisher.class.getClassLoader());
if (context.container().configuration().mode()!=Mode.root)
Thread.currentThread().setContextClassLoader(ProfilePublisher.class.getClassLoader());
profile = publisher.remove(profile, resolveScopesFromTokens(tokens));
} catch (Exception e) {
rethrowUnchecked(e);
} finally{
SecurityTokenProvider.instance.set(previousToken);
Thread.currentThread().setContextClassLoader(contextCL);
if (context.container().configuration().mode()!=Mode.root)
Thread.currentThread().setContextClassLoader(contextCL);
}
log.debug("after remove application profile contains scopes {}",profile.scopes().asCollection());
sharePublished(profile);

View File

@ -42,6 +42,7 @@ public class RequestAccounting extends RequestHandler {
calledMethod = e.request().getRequestURI().substring(e.request().getContextPath().length());
if (calledMethod.isEmpty())
calledMethod = "/";
calledMethod= e.request().getMethod()+" "+calledMethod;
}
InnerMethodName.instance.set(calledMethod);
String caller = AuthorizationProvider.instance.get()!=null? AuthorizationProvider.instance.get().getClient().getId(): "UNKNOWN";

View File

@ -6,15 +6,23 @@ import static org.gcube.smartgears.Constants.token_header;
import static org.gcube.smartgears.handlers.application.request.RequestError.internal_server_error;
import static org.gcube.smartgears.handlers.application.request.RequestError.invalid_request_error;
import javax.xml.bind.DatatypeConverter;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Base64;
import java.util.List;
import javax.xml.bind.annotation.XmlRootElement;
import org.gcube.common.authorization.client.exceptions.ObjectNotFound;
import org.gcube.common.authorization.library.AuthorizationEntry;
import org.gcube.common.authorization.library.provider.AuthorizationProvider;
import org.gcube.common.authorization.library.provider.SecurityTokenProvider;
import org.gcube.common.authorization.library.provider.UmaJWTProvider;
import org.gcube.common.authorization.library.provider.UserInfo;
import org.gcube.common.authorization.library.utils.Caller;
import org.gcube.common.scope.api.ScopeProvider;
import org.gcube.common.scope.impl.ScopeBean;
import org.gcube.smartgears.Constants;
import org.gcube.smartgears.handlers.application.RequestEvent;
import org.gcube.smartgears.handlers.application.RequestHandler;
@ -22,6 +30,10 @@ import org.gcube.smartgears.handlers.application.ResponseEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.eclipsesource.json.Json;
import com.eclipsesource.json.JsonArray;
import com.eclipsesource.json.JsonObject;
@XmlRootElement(name = Constants.request_context_retriever)
public class RequestContextRetriever extends RequestHandler {
@ -40,24 +52,30 @@ public class RequestContextRetriever extends RequestHandler {
public void handleRequest(RequestEvent call) {
String token = call.request().getParameter(token_header)==null? call.request().getHeader(token_header):call.request().getParameter(token_header);
String scope = call.request().getParameter(scope_header)==null? call.request().getHeader(scope_header):call.request().getParameter(scope_header);
if (token==null && call.request().getHeader(Constants.authorization_header)!=null){
String authorization = call.request().getHeader(Constants.authorization_header);
if (authorization.contains(BASIC_AUTH_PREFIX)) {
String base64Credentials = authorization.substring(BASIC_AUTH_PREFIX.length()).trim();
String credentials = new String(DatatypeConverter.parseBase64Binary(base64Credentials));
// credentials = username:password
final String[] values = credentials.split(":",2);
token = values[1];
} else if (authorization.contains(BEARER_AUTH_PREFIX))
token = authorization.substring(BEARER_AUTH_PREFIX.length()).trim();
String authHeader = call.request().getHeader(Constants.authorization_header);
log.trace("auth header is {}",authHeader);
String umaToken = null;
if (authHeader!=null && !authHeader.isEmpty()) {
if (authHeader.startsWith(BEARER_AUTH_PREFIX))
umaToken = authHeader.substring(BEARER_AUTH_PREFIX.length()).trim();
else if (token==null && authHeader.startsWith(BASIC_AUTH_PREFIX)) {
String basicAuthToken = authHeader.substring(BASIC_AUTH_PREFIX.length()).trim();
String decodedAuth = new String(Base64.getDecoder().decode(basicAuthToken.getBytes()));
token = decodedAuth.split(":")[1];
}
}
//Gives priority to the token
if (token!=null)
this.retreiveAndSetInfo(token, call);
if (umaToken!=null) {
this.retreiveAndSetInfoUmaToken(umaToken, token, call);
} else if (token!=null)
this.retreiveAndSetInfoGcubeToken(token, call);
else if (scope!=null)
ScopeProvider.instance.set(scope);
@ -67,12 +85,13 @@ public class RequestContextRetriever extends RequestHandler {
public void handleResponse(ResponseEvent e) {
SecurityTokenProvider.instance.reset();
AuthorizationProvider.instance.reset();
UmaJWTProvider.instance.reset();
ScopeProvider.instance.reset();
log.debug("resetting all the Thread local for this call.");
}
private void retreiveAndSetInfo(String token, RequestEvent call){
log.info("retrieving context using token {} ", token);
private void retreiveAndSetInfoGcubeToken(String token, RequestEvent call){
log.trace("retrieving context using token {} ", token);
AuthorizationEntry authEntry = null;
try{
authEntry = authorizationService().get(token);
@ -89,4 +108,55 @@ public class RequestContextRetriever extends RequestHandler {
ScopeProvider.instance.set(authEntry.getContext());
log.info("retrieved request authorization info {} in scope {} ", AuthorizationProvider.instance.get(), authEntry.getContext());
}
private void retreiveAndSetInfoUmaToken(String umaToken, String gcubeToken, RequestEvent call){
log.debug("using UMA token for authorization");
log.trace("retrieving context using uma token {} ", umaToken);
UmaJWTProvider.instance.set(umaToken);
SecurityTokenProvider.instance.set(gcubeToken);
parseUmaTokenAndSet(umaToken);
log.info("retrieved request authorization info {} in scope {} ", AuthorizationProvider.instance.get(), ScopeProvider.instance.get());
}
private void parseUmaTokenAndSet(String umaToken) {
String realUmaTokenEncoded = umaToken.split("\\.")[1];
String realUmaToken = new String(Base64.getDecoder().decode(realUmaTokenEncoded.getBytes()));
JsonObject object = Json.parse(realUmaToken).asObject();
String username = object.get("preferred_username").asString();
String scope = object.getString("aud", null);
log.trace("token related context is {}", scope);
JsonObject resource = object.get("resource_access").asObject();
log.trace("resource access is {}", resource.toString());
JsonObject scopeObject = resource.get(scope).asObject();
ScopeBean scopeBean = null;
try {
String decodedName = URLDecoder.decode(scope, StandardCharsets.UTF_8.toString());
scopeBean = new ScopeBean(decodedName);
}catch(Exception e){
log.error("error decoding uma token",e);
internal_server_error.fire("error contacting authorization service");
}
JsonArray roles = scopeObject.get("roles").asArray();
List<String> userRoles = new ArrayList<String>();
roles.forEach((e)->userRoles.add(e.asString()));
AuthorizationProvider.instance.set(new Caller(new UserInfo(username, userRoles), "token"));
ScopeProvider.instance.set(scopeBean.toString());
}
}

View File

@ -1,9 +1,7 @@
package org.gcube.smartgears.handlers.application.request;
import static org.gcube.common.authorization.client.Constants.authorizationService;
import static org.gcube.smartgears.handlers.application.request.RequestError.application_failed_error;
import static org.gcube.smartgears.handlers.application.request.RequestError.application_unavailable_error;
import static org.gcube.smartgears.handlers.application.request.RequestError.internal_server_error;
import static org.gcube.smartgears.handlers.application.request.RequestError.invalid_request_error;
import java.io.IOException;
@ -11,12 +9,7 @@ import java.io.IOException;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlRootElement;
import org.gcube.common.authorization.client.exceptions.ObjectNotFound;
import org.gcube.common.authorization.library.AuthorizationEntry;
import org.gcube.common.authorization.library.PolicyUtils;
import org.gcube.common.authorization.library.policies.Policy;
import org.gcube.common.authorization.library.provider.SecurityTokenProvider;
import org.gcube.common.authorization.library.provider.ServiceIdentifier;
import org.gcube.common.scope.api.ScopeProvider;
import org.gcube.common.scope.impl.ScopeBean;
import org.gcube.common.scope.impl.ScopeBean.Type;
@ -25,7 +18,6 @@ import org.gcube.smartgears.configuration.container.ContainerConfiguration;
import org.gcube.smartgears.context.application.ApplicationContext;
import org.gcube.smartgears.handlers.application.RequestEvent;
import org.gcube.smartgears.handlers.application.RequestHandler;
import org.gcube.smartgears.utils.Utils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -58,8 +50,8 @@ public class RequestValidator extends RequestHandler {
validateScopeCall();
if (SecurityTokenProvider.instance.get()!=null)
validatePolicy(SecurityTokenProvider.instance.get(), call);
/*if (SecurityTokenProvider.instance.get()!=null)
validatePolicy(SecurityTokenProvider.instance.get(), call);*/
}
@ -128,6 +120,7 @@ public class RequestValidator extends RequestHandler {
return getName();
}
/*
private void validatePolicy(String token, RequestEvent call){
log.info("accessing policy validator with token {} ", token);
AuthorizationEntry authEntry = null;
@ -149,7 +142,7 @@ public class RequestValidator extends RequestHandler {
invalid_request_error.fire("rejecting call to "+context.name()+": "+authEntry.getClientInfo().getId()+" is not allowed to contact the service");
}
}
}*/

View File

@ -11,6 +11,7 @@ import org.gcube.common.authorization.client.proxy.AuthorizationProxy;
import org.gcube.common.authorization.library.provider.SecurityTokenProvider;
import org.gcube.common.resources.gcore.HostingNode;
import org.gcube.informationsystem.publisher.ScopedPublisher;
import org.gcube.smartgears.configuration.Mode;
import org.gcube.smartgears.context.container.ContainerContext;
import org.gcube.smartgears.handlers.ProfileEvents;
import org.gcube.smartgears.provider.ProviderFactory;
@ -88,18 +89,20 @@ public class ProfilePublisher {
}*/
ClassLoader contextCL = Thread.currentThread().getContextClassLoader();
log.debug("using context {}",contextCL.getClass().getSimpleName());
String previousToken = SecurityTokenProvider.instance.get();
try{//This classloader set is needed for the jaxb context
if (previousToken==null)
SecurityTokenProvider.instance.set((String)tokens.toArray()[0]);
Thread.currentThread().setContextClassLoader(ProfilePublisher.class.getClassLoader());
if (context.configuration().mode()!=Mode.root)
Thread.currentThread().setContextClassLoader(ProfilePublisher.class.getClassLoader());
profile = publisher.create(profile, resolveScopesFromTokens(tokens));
} catch (Exception e) {
rethrowUnchecked(e);
} finally {
SecurityTokenProvider.instance.set(previousToken);
Thread.currentThread().setContextClassLoader(contextCL);
if (context.configuration().mode()!=Mode.root)
Thread.currentThread().setContextClassLoader(contextCL);
}
sharePublished(profile);
@ -147,19 +150,21 @@ public class ProfilePublisher {
log.debug("[update] resource scopes are : {} ",profile.scopes().asCollection());
ClassLoader contextCL = Thread.currentThread().getContextClassLoader();
log.debug("using context {}",contextCL.getClass().getSimpleName());
String previousToken = SecurityTokenProvider.instance.get();
try{//This classloader set is needed for the jaxb context
if (previousToken==null)
SecurityTokenProvider.instance.set((String)context.configuration().startTokens().toArray()[0]);
Thread.currentThread().setContextClassLoader(ProfilePublisher.class.getClassLoader());
if (context.configuration().mode()!=Mode.root)
Thread.currentThread().setContextClassLoader(ProfilePublisher.class.getClassLoader());
profile = publisher.update(profile);
} catch (Exception e) {
rethrowUnchecked(e);
} finally {
SecurityTokenProvider.instance.set(previousToken);
Thread.currentThread().setContextClassLoader(contextCL);
if (context.configuration().mode()!=Mode.root)
Thread.currentThread().setContextClassLoader(contextCL);
}
sharePublished(profile);
@ -198,18 +203,20 @@ public class ProfilePublisher {
} */
ClassLoader contextCL = Thread.currentThread().getContextClassLoader();
log.debug("using context {}",contextCL.getClass().getSimpleName());
String previousToken = SecurityTokenProvider.instance.get();
try{//This classloader set is needed for the jaxb context
if (previousToken==null)
SecurityTokenProvider.instance.set((String)tokens.toArray()[0]);
Thread.currentThread().setContextClassLoader(ProfilePublisher.class.getClassLoader());
if (context.configuration().mode()!=Mode.root)
Thread.currentThread().setContextClassLoader(ProfilePublisher.class.getClassLoader());
profile = publisher.remove(profile, resolveScopesFromTokens(tokens));
} catch (Exception e) {
rethrowUnchecked(e);
} finally {
SecurityTokenProvider.instance.set(previousToken);
Thread.currentThread().setContextClassLoader(contextCL);
if (context.configuration().mode()!=Mode.root)
Thread.currentThread().setContextClassLoader(contextCL);
}
log.debug("after remove container profile contains scopes {}",profile.scopes().asCollection());