package org.gcube.datatransfer.resolver.services; import static org.gcube.resources.discovery.icclient.ICFactory.clientFor; import static org.gcube.resources.discovery.icclient.ICFactory.queryFor; import java.io.BufferedInputStream; import java.io.InputStream; import java.util.Collection; import java.util.List; import javax.servlet.http.HttpServletRequest; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.Context; import javax.ws.rs.core.Response; import org.apache.http.HttpResponse; import org.apache.http.HttpStatus; import org.apache.http.auth.AuthScope; import org.apache.http.auth.UsernamePasswordCredentials; import org.apache.http.client.CredentialsProvider; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.BasicCredentialsProvider; import org.apache.http.impl.client.HttpClientBuilder; import org.gcube.common.authorization.library.provider.SecurityTokenProvider; import org.gcube.common.encryption.StringEncrypter; import org.gcube.common.resources.gcore.ServiceEndpoint; import org.gcube.common.resources.gcore.ServiceEndpoint.AccessPoint; import org.gcube.common.resources.gcore.ServiceEndpoint.Property; import org.gcube.common.scope.api.ScopeProvider; import org.gcube.datatransfer.resolver.requesthandler.RequestHandler; import org.gcube.datatransfer.resolver.services.error.ExceptionManager; import org.gcube.resources.discovery.client.api.DiscoveryClient; import org.gcube.resources.discovery.client.queries.api.SimpleQuery; import org.slf4j.Logger; import org.slf4j.LoggerFactory; // TODO: Auto-generated Javadoc /** * The Class WekeoResolver. * * @author Francesco Mangiacrapa at ISTI-CNR francesco.mangiacrapa@isti.cnr.it * * Mar 30, 2021 */ @Path("wekeo") public class WekeoResolver { private static Logger logger = LoggerFactory.getLogger(WekeoResolver.class); private final static String RUNTIME_WKEO_RESOURCE_NAME = "WekeoDataBroker"; private final static String CATEGORY_WEKEO_TYPE = "OnlineService"; private static String helpURI = "https://wiki.gcube-system.org/gcube/URI_Resolver#Wekeo_Resolver"; /** * Gets the token. * * @param req the req * @return the token * @throws WebApplicationException the web application exception */ @GET @Path("/gettoken") public Response getToken(@Context HttpServletRequest req) throws WebApplicationException{ logger.info(this.getClass().getSimpleName()+" getToken starts..."); String wekeoToken = null; try { String contextToken = SecurityTokenProvider.instance.get(); String scope = ScopeProvider.instance.get(); logger.info("ScopeProvider has scope: "+scope); String appToken = req.getServletContext().getInitParameter(RequestHandler.ROOT_APP_TOKEN); if(contextToken.compareTo(appToken)==0){ logger.error("Token not passed, SecurityTokenProvider contains the root app token: "+appToken.substring(0,10)+"..."); throw ExceptionManager.unauthorizedException(req, "You are not authorized. You must pass a token of VRE", this.getClass(), helpURI); } AccessPoint wekeoAccessPoint = readWekeoServiceEndpoint(req, scope); if(wekeoAccessPoint!=null) { String wekeoUsername = wekeoAccessPoint.username(); String wekeoAddress = wekeoAccessPoint.address(); String wekeoPwd = wekeoAccessPoint.password(); //printing the access point found if(logger.isDebugEnabled()) { String msg = String.format("Found the username %s and the address %s to perform the request", wekeoUsername, wekeoAddress); logger.debug(msg); } //decrypting the pwd if(wekeoPwd!=null){ wekeoPwd = StringEncrypter.getEncrypter().decrypt(wekeoAccessPoint.password()); logger.info("Returning decrypted pwd registered into "+RUNTIME_WKEO_RESOURCE_NAME +" SE: "+wekeoPwd.substring(0,wekeoPwd.length()/2)+"...."); } if(wekeoUsername!=null && wekeoPwd!=null & wekeoAddress!=null) { try { //performing the HTTP request with Basic Authentication CredentialsProvider provider = new BasicCredentialsProvider(); UsernamePasswordCredentials credentials = new UsernamePasswordCredentials(wekeoUsername, wekeoPwd); provider.setCredentials(AuthScope.ANY, credentials); HttpClient client = HttpClientBuilder.create().setDefaultCredentialsProvider(provider).build(); logger.info("calling the URL and performing basic authentication to: "+wekeoAddress); HttpResponse response = client.execute(new HttpGet(wekeoAddress)); int statusCode = response.getStatusLine().getStatusCode(); logger.info("the response stus code is: "+statusCode); if(statusCode == 200) { InputStream is = response.getEntity().getContent(); BufferedInputStream bif = new BufferedInputStream(is); wekeoToken = bif.toString(); logger.info("got the wekeo token: "+wekeoToken.substring(0,wekeoToken.length()/2)+"...."); }else { String error = String.format("The request to %s returned status code %d",wekeoAddress,statusCode); throw ExceptionManager.internalErrorException(req, error, this.getClass(), helpURI); } }catch (Exception e) { String error = String.format("Error on performing request to %s",wekeoAddress); throw ExceptionManager.internalErrorException(req, error, this.getClass(), helpURI); } }else { String error = String.format("I cannot read the configurations (adress, username,password) from %s in the scope %s",RUNTIME_WKEO_RESOURCE_NAME,scope); throw ExceptionManager.internalErrorException(req, error, this.getClass(), helpURI); } } //to be sure if(wekeoToken==null) { String error = String.format("Sorry an rrror occured on getting the wekeo token. Please, retry the request"); throw ExceptionManager.internalErrorException(req, error, this.getClass(), helpURI); } return Response.ok(wekeoToken).build(); }catch (Exception e) { //ALREADY MANAGED AS WebApplicationException logger.error("Exception:", e); throw (WebApplicationException) e; } } /** * Reads the wekeo endpoint information from IS. {The SE name is: @link WekeoResolver#RUNTIME_WKEO_RESOURCE_NAME} * * @param req the req * @param scope the scope * @return the string */ public static AccessPoint readWekeoServiceEndpoint(HttpServletRequest req, String scope){ String callerScope = null; try{ callerScope = ScopeProvider.instance.get(); ScopeProvider.instance.set(scope); logger.info("Searching SE "+RUNTIME_WKEO_RESOURCE_NAME+" configurations in the scope: "+ScopeProvider.instance.get()); SimpleQuery query = queryFor(ServiceEndpoint.class); query.addCondition("$resource/Profile/Name/text() eq '"+ RUNTIME_WKEO_RESOURCE_NAME +"'"); query.addCondition("$resource/Profile/Category/text() eq '"+ CATEGORY_WEKEO_TYPE +"'"); DiscoveryClient client = clientFor(ServiceEndpoint.class); List toReturn = client.submit(query); logger.info("The query returned "+toReturn.size()+ " ServiceEndpoint/s"); if(toReturn.size()==0){ String errorMessage = String.format("Missing the RR with Name '%s' and Category '%s' in the scope '%s'. Please contact the support.",RUNTIME_WKEO_RESOURCE_NAME,CATEGORY_WEKEO_TYPE,ScopeProvider.instance.get()); logger.error(errorMessage); throw ExceptionManager.internalErrorException(req, errorMessage, AnalyticsCreateResolver.class, helpURI); } String wekeoUsername = null; String wekeoPwd = null; ServiceEndpoint se = toReturn.get(0); Collection theAccessPoints = se.profile().accessPoints().asCollection(); for (AccessPoint accessPoint : theAccessPoints) { wekeoUsername = accessPoint.username(); wekeoPwd = accessPoint.password(); if(wekeoUsername!=null && wekeoPwd!=null) { logger.info("returning the access point with name: "+accessPoint.name()); return accessPoint; } } return null; }catch(Exception e){ String errorMessage = "Error occurred on reading the "+RUNTIME_WKEO_RESOURCE_NAME+" SE registered in the scope: "+ScopeProvider.instance.get(); logger.error(errorMessage, e); throw ExceptionManager.internalErrorException(req, errorMessage, AnalyticsCreateResolver.class, helpURI); }finally{ if(callerScope!=null){ logger.info("Setting to the callerScope scope: "+callerScope); ScopeProvider.instance.set(callerScope); }else{ logger.info("Reset scope"); ScopeProvider.instance.reset(); } } } }