2021-03-30 18:21:49 +02:00
|
|
|
package org.gcube.datatransfer.resolver.services;
|
|
|
|
|
|
|
|
import static org.gcube.resources.discovery.icclient.ICFactory.clientFor;
|
|
|
|
import static org.gcube.resources.discovery.icclient.ICFactory.queryFor;
|
|
|
|
|
2021-04-08 10:25:48 +02:00
|
|
|
import java.io.File;
|
|
|
|
import java.io.FileInputStream;
|
2021-03-31 18:02:54 +02:00
|
|
|
import java.io.InputStream;
|
2021-04-07 12:19:51 +02:00
|
|
|
import java.io.InputStreamReader;
|
|
|
|
import java.net.HttpURLConnection;
|
|
|
|
import java.net.URL;
|
2021-03-30 18:21:49 +02:00
|
|
|
import java.util.Collection;
|
|
|
|
import java.util.List;
|
|
|
|
|
|
|
|
import javax.servlet.http.HttpServletRequest;
|
|
|
|
import javax.ws.rs.GET;
|
|
|
|
import javax.ws.rs.Path;
|
2021-04-07 15:04:17 +02:00
|
|
|
import javax.ws.rs.Produces;
|
2021-03-30 18:21:49 +02:00
|
|
|
import javax.ws.rs.WebApplicationException;
|
|
|
|
import javax.ws.rs.core.Context;
|
2021-04-07 15:04:17 +02:00
|
|
|
import javax.ws.rs.core.MediaType;
|
2021-03-30 18:21:49 +02:00
|
|
|
import javax.ws.rs.core.Response;
|
|
|
|
|
2021-04-07 12:19:51 +02:00
|
|
|
import org.apache.commons.codec.binary.Base64;
|
2021-03-30 18:21:49 +02:00
|
|
|
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.scope.api.ScopeProvider;
|
|
|
|
import org.gcube.datatransfer.resolver.requesthandler.RequestHandler;
|
|
|
|
import org.gcube.datatransfer.resolver.services.error.ExceptionManager;
|
2021-04-08 12:19:55 +02:00
|
|
|
import org.gcube.datatransfer.resolver.services.exceptions.NotFoundException;
|
2021-03-30 18:21:49 +02:00
|
|
|
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;
|
|
|
|
|
|
|
|
/**
|
2022-03-31 10:52:52 +02:00
|
|
|
* The WekeoResolver provides a method to wrap the basic authentication from
|
|
|
|
* D4Science account to WekeoBroker service.
|
|
|
|
*
|
|
|
|
* Request format
|
|
|
|
* [URI_RESOLVER_SERVICE_ENDPOINT]/wekeo/gettoken?gcube-token=[YOUR_GCUBE_TOKEN]
|
|
|
|
*
|
|
|
|
* See more at
|
|
|
|
* https://gcube.wiki.gcube-system.org/gcube/URI_Resolver#Wekeo_Resolver
|
2021-03-30 18:21:49 +02:00
|
|
|
*
|
|
|
|
* @author Francesco Mangiacrapa at ISTI-CNR francesco.mangiacrapa@isti.cnr.it
|
|
|
|
*
|
2022-03-24 17:33:54 +01:00
|
|
|
* Mar 24, 2022
|
2021-03-30 18:21:49 +02:00
|
|
|
*/
|
|
|
|
@Path("wekeo")
|
|
|
|
public class WekeoResolver {
|
|
|
|
|
|
|
|
private static Logger logger = LoggerFactory.getLogger(WekeoResolver.class);
|
2022-03-24 17:33:54 +01:00
|
|
|
|
2021-03-30 18:21:49 +02:00
|
|
|
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
|
|
|
|
*/
|
2021-04-07 16:55:12 +02:00
|
|
|
@GET
|
2021-03-30 18:21:49 +02:00
|
|
|
@Path("/gettoken")
|
2021-04-07 15:04:17 +02:00
|
|
|
@Produces(MediaType.APPLICATION_JSON)
|
2022-03-24 17:33:54 +01:00
|
|
|
public Response getToken(@Context HttpServletRequest req) throws WebApplicationException {
|
|
|
|
|
|
|
|
logger.info(this.getClass().getSimpleName() + " getToken starts...");
|
|
|
|
|
2021-03-30 18:21:49 +02:00
|
|
|
try {
|
2022-03-24 17:33:54 +01:00
|
|
|
|
2021-03-30 18:21:49 +02:00
|
|
|
String contextToken = SecurityTokenProvider.instance.get();
|
|
|
|
String scope = ScopeProvider.instance.get();
|
2022-03-24 17:33:54 +01:00
|
|
|
logger.info("ScopeProvider has scope: " + scope);
|
2021-03-30 18:21:49 +02:00
|
|
|
|
|
|
|
String appToken = req.getServletContext().getInitParameter(RequestHandler.ROOT_APP_TOKEN);
|
|
|
|
|
2022-03-24 17:33:54 +01:00
|
|
|
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);
|
2021-03-30 18:21:49 +02:00
|
|
|
}
|
2022-03-24 17:33:54 +01:00
|
|
|
|
2021-04-07 12:19:51 +02:00
|
|
|
StringBuilder wekeoResponse = new StringBuilder();
|
|
|
|
AccessPoint wekeoAccessPoint = WekeoResolver.readWekeoServiceEndpoint(req, scope);
|
|
|
|
|
|
|
|
if (wekeoAccessPoint != null) {
|
|
|
|
|
2021-03-31 18:02:54 +02:00
|
|
|
String wekeoUsername = wekeoAccessPoint.username();
|
|
|
|
String wekeoAddress = wekeoAccessPoint.address();
|
|
|
|
String wekeoPwd = wekeoAccessPoint.password();
|
2021-04-07 12:19:51 +02:00
|
|
|
|
|
|
|
// 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);
|
2021-03-31 18:02:54 +02:00
|
|
|
logger.debug(msg);
|
|
|
|
}
|
2021-04-07 12:19:51 +02:00
|
|
|
|
2022-03-24 17:33:54 +01:00
|
|
|
logger.info("The pwd is: " + wekeoPwd);
|
2021-04-07 12:19:51 +02:00
|
|
|
// decrypting the pwd
|
|
|
|
if (wekeoPwd != null) {
|
|
|
|
wekeoPwd = StringEncrypter.getEncrypter().decrypt(wekeoPwd);
|
|
|
|
logger.info("Decrypted pwd registered into Access Point '" + wekeoAccessPoint.name() + "' is: "
|
2022-03-24 17:33:54 +01:00
|
|
|
+ wekeoPwd.substring(0, wekeoPwd.length() / 2) + "...");
|
2021-03-31 18:02:54 +02:00
|
|
|
}
|
2021-04-07 12:19:51 +02:00
|
|
|
|
|
|
|
if (wekeoUsername != null && wekeoPwd != null & wekeoAddress != null) {
|
|
|
|
HttpURLConnection connection = null;
|
|
|
|
InputStream content = null;
|
|
|
|
InputStreamReader in = null;
|
2021-03-31 18:02:54 +02:00
|
|
|
try {
|
2021-04-07 12:19:51 +02:00
|
|
|
|
|
|
|
String authString = wekeoUsername + ":" + wekeoPwd;
|
|
|
|
byte[] authEncBytes = Base64.encodeBase64(authString.getBytes());
|
|
|
|
String authStringEnc = new String(authEncBytes);
|
|
|
|
logger.debug("Base64 encoded auth string: " + authStringEnc);
|
|
|
|
|
2022-03-24 17:33:54 +01:00
|
|
|
logger.info("Performing the request to: " + wekeoAddress);
|
2021-04-07 12:19:51 +02:00
|
|
|
URL url = new URL(wekeoAddress);
|
|
|
|
connection = (HttpURLConnection) url.openConnection();
|
|
|
|
connection.setRequestMethod("GET");
|
|
|
|
connection.setDoOutput(true);
|
|
|
|
connection.setRequestProperty("Authorization", "Basic " + authStringEnc);
|
2022-03-24 17:33:54 +01:00
|
|
|
|
2021-04-07 12:19:51 +02:00
|
|
|
content = (InputStream) connection.getInputStream();
|
|
|
|
in = new InputStreamReader(content);
|
2022-03-24 17:33:54 +01:00
|
|
|
|
|
|
|
logger.info("the response code is: " + connection.getResponseCode());
|
|
|
|
|
2021-04-07 12:19:51 +02:00
|
|
|
int numCharsRead;
|
|
|
|
char[] charArray = new char[1024];
|
|
|
|
StringBuffer sb = new StringBuffer();
|
|
|
|
logger.debug("reading the response...");
|
|
|
|
while ((numCharsRead = in.read(charArray)) > 0) {
|
|
|
|
sb.append(charArray, 0, numCharsRead);
|
|
|
|
}
|
|
|
|
wekeoResponse.append(sb.toString());
|
2022-03-24 17:33:54 +01:00
|
|
|
// System.out.println(wekeoResponse);
|
2021-04-07 12:19:51 +02:00
|
|
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
logger.error(e.getMessage(), e);
|
|
|
|
String error = String.format("Error on performing request to %s", wekeoAddress);
|
|
|
|
throw new Exception(error);
|
|
|
|
} finally {
|
|
|
|
try {
|
2022-03-24 17:33:54 +01:00
|
|
|
if (content != null && in != null) {
|
2021-04-07 12:19:51 +02:00
|
|
|
in.close();
|
|
|
|
content.close();
|
|
|
|
}
|
2022-03-24 17:33:54 +01:00
|
|
|
} catch (Exception e) {
|
|
|
|
// silent
|
2021-03-31 18:02:54 +02:00
|
|
|
}
|
|
|
|
}
|
2021-04-07 12:19:51 +02:00
|
|
|
|
|
|
|
} 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 new Exception(error);
|
2021-03-31 18:02:54 +02:00
|
|
|
}
|
2021-03-30 18:21:49 +02:00
|
|
|
}
|
2021-04-07 12:19:51 +02:00
|
|
|
|
|
|
|
// to be sure
|
|
|
|
if (wekeoResponse.length() == 0) {
|
2022-03-24 17:33:54 +01:00
|
|
|
String error = String.format(
|
|
|
|
"Sorry an error occured on getting the access token from Wekeo. Please, retry the request");
|
2021-04-07 12:19:51 +02:00
|
|
|
throw new Exception(error);
|
2021-03-31 18:02:54 +02:00
|
|
|
}
|
2022-03-24 17:33:54 +01:00
|
|
|
|
2021-04-07 12:19:51 +02:00
|
|
|
String theResponse = wekeoResponse.toString();
|
2022-03-24 17:33:54 +01:00
|
|
|
logger.info("returning: \n" + theResponse);
|
|
|
|
|
2021-04-07 12:19:51 +02:00
|
|
|
return Response.ok(theResponse).build();
|
2022-03-24 17:33:54 +01:00
|
|
|
} catch (Exception e) {
|
|
|
|
// ALREADY MANAGED AS WebApplicationException
|
2021-03-30 18:21:49 +02:00
|
|
|
logger.error("Exception:", e);
|
|
|
|
throw (WebApplicationException) e;
|
|
|
|
}
|
|
|
|
}
|
2022-03-24 17:33:54 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Index.
|
|
|
|
*
|
|
|
|
* @param req the req
|
|
|
|
* @return the input stream
|
|
|
|
* @throws WebApplicationException the web application exception
|
|
|
|
*/
|
2021-04-07 16:55:12 +02:00
|
|
|
@GET
|
2022-03-24 17:33:54 +01:00
|
|
|
@Produces({ MediaType.TEXT_HTML })
|
2021-04-08 12:59:39 +02:00
|
|
|
@Path("")
|
2022-03-24 17:33:54 +01:00
|
|
|
public InputStream index(@Context HttpServletRequest req) throws WebApplicationException {
|
2021-04-08 10:25:48 +02:00
|
|
|
|
|
|
|
String indexFile = "/WEB-INF/jsp/wekeo.jsp";
|
|
|
|
|
2022-03-24 17:33:54 +01:00
|
|
|
try {
|
|
|
|
logger.info(this.getClass().getSimpleName() + " index called");
|
|
|
|
String realPath = req.getServletContext().getRealPath(indexFile);
|
|
|
|
return new FileInputStream(new File(realPath));
|
|
|
|
} catch (Exception e) {
|
2021-04-08 10:25:48 +02:00
|
|
|
|
2022-03-24 17:33:54 +01:00
|
|
|
if (!(e instanceof WebApplicationException)) {
|
|
|
|
// UNEXPECTED EXCEPTION managing it as WebApplicationException
|
2021-04-08 12:28:30 +02:00
|
|
|
String error = "wekeo.jsp not found. Please, contact the support!";
|
2021-04-08 10:25:48 +02:00
|
|
|
throw ExceptionManager.internalErrorException(req, error, this.getClass(), null);
|
|
|
|
}
|
2022-03-24 17:33:54 +01:00
|
|
|
// ALREADY MANAGED AS WebApplicationException
|
2021-04-08 10:25:48 +02:00
|
|
|
logger.error("Exception:", e);
|
|
|
|
throw (WebApplicationException) e;
|
|
|
|
}
|
2021-04-07 16:55:12 +02:00
|
|
|
}
|
2022-03-24 17:33:54 +01:00
|
|
|
|
2021-03-30 18:21:49 +02:00
|
|
|
/**
|
2022-03-24 17:33:54 +01:00
|
|
|
* Reads the wekeo endpoint information from IS. {The SE name is: @link
|
|
|
|
* WekeoResolver#RUNTIME_WKEO_RESOURCE_NAME}
|
2021-03-30 18:21:49 +02:00
|
|
|
*
|
2022-03-24 17:33:54 +01:00
|
|
|
* @param req the req
|
2021-03-30 18:21:49 +02:00
|
|
|
* @param scope the scope
|
|
|
|
* @return the string
|
|
|
|
*/
|
2022-03-24 17:33:54 +01:00
|
|
|
public static AccessPoint readWekeoServiceEndpoint(HttpServletRequest req, String scope) {
|
2021-03-30 18:21:49 +02:00
|
|
|
|
|
|
|
String callerScope = null;
|
2022-03-24 17:33:54 +01:00
|
|
|
try {
|
2021-03-30 18:21:49 +02:00
|
|
|
callerScope = ScopeProvider.instance.get();
|
|
|
|
ScopeProvider.instance.set(scope);
|
2022-03-24 17:33:54 +01:00
|
|
|
logger.info("Searching SE " + RUNTIME_WKEO_RESOURCE_NAME + " configurations in the scope: "
|
|
|
|
+ ScopeProvider.instance.get());
|
2021-03-30 18:21:49 +02:00
|
|
|
|
|
|
|
SimpleQuery query = queryFor(ServiceEndpoint.class);
|
2022-03-24 17:33:54 +01:00
|
|
|
query.addCondition("$resource/Profile/Name/text() eq '" + RUNTIME_WKEO_RESOURCE_NAME + "'");
|
|
|
|
query.addCondition("$resource/Profile/Category/text() eq '" + CATEGORY_WEKEO_TYPE + "'");
|
2021-03-30 18:21:49 +02:00
|
|
|
|
|
|
|
DiscoveryClient<ServiceEndpoint> client = clientFor(ServiceEndpoint.class);
|
|
|
|
List<ServiceEndpoint> toReturn = client.submit(query);
|
|
|
|
|
2022-03-24 17:33:54 +01:00
|
|
|
logger.info("The query returned " + toReturn.size() + " ServiceEndpoint/s");
|
2021-03-30 18:21:49 +02:00
|
|
|
|
2022-03-24 17:33:54 +01:00
|
|
|
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());
|
2021-03-30 18:21:49 +02:00
|
|
|
logger.error(errorMessage);
|
2021-04-08 12:19:55 +02:00
|
|
|
throw ExceptionManager.notFoundException(req, errorMessage, WekeoResolver.class, helpURI);
|
|
|
|
|
2021-03-30 18:21:49 +02:00
|
|
|
}
|
|
|
|
|
2021-03-31 18:02:54 +02:00
|
|
|
String wekeoUsername = null;
|
|
|
|
String wekeoPwd = null;
|
2022-03-24 17:33:54 +01:00
|
|
|
|
2021-03-30 18:21:49 +02:00
|
|
|
ServiceEndpoint se = toReturn.get(0);
|
|
|
|
Collection<AccessPoint> theAccessPoints = se.profile().accessPoints().asCollection();
|
|
|
|
for (AccessPoint accessPoint : theAccessPoints) {
|
2021-03-31 18:02:54 +02:00
|
|
|
wekeoUsername = accessPoint.username();
|
|
|
|
wekeoPwd = accessPoint.password();
|
2022-03-24 17:33:54 +01:00
|
|
|
if (wekeoUsername != null && wekeoPwd != null) {
|
|
|
|
logger.info("returning the access point with name: " + accessPoint.name());
|
2021-03-31 18:02:54 +02:00
|
|
|
return accessPoint;
|
2021-03-30 18:21:49 +02:00
|
|
|
}
|
|
|
|
}
|
2022-03-24 17:33:54 +01:00
|
|
|
|
2021-03-30 18:21:49 +02:00
|
|
|
return null;
|
|
|
|
|
2022-03-24 17:33:54 +01:00
|
|
|
} catch (Exception e) {
|
|
|
|
|
|
|
|
if (e instanceof NotFoundException)
|
2021-04-08 12:19:55 +02:00
|
|
|
throw e;
|
2022-03-24 17:33:54 +01:00
|
|
|
|
|
|
|
String errorMessage = "Error occurred on reading the " + RUNTIME_WKEO_RESOURCE_NAME
|
|
|
|
+ " SE registered in the scope: " + ScopeProvider.instance.get();
|
2021-03-30 18:21:49 +02:00
|
|
|
logger.error(errorMessage, e);
|
2021-04-08 10:25:48 +02:00
|
|
|
throw ExceptionManager.internalErrorException(req, errorMessage, WekeoResolver.class, helpURI);
|
2021-03-30 18:21:49 +02:00
|
|
|
|
2022-03-24 17:33:54 +01:00
|
|
|
} finally {
|
|
|
|
if (callerScope != null) {
|
|
|
|
logger.info("Setting to the callerScope scope: " + callerScope);
|
2021-03-30 18:21:49 +02:00
|
|
|
ScopeProvider.instance.set(callerScope);
|
2022-03-24 17:33:54 +01:00
|
|
|
} else {
|
2021-03-30 18:21:49 +02:00
|
|
|
logger.info("Reset scope");
|
|
|
|
ScopeProvider.instance.reset();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|