new_rstudio_server_integration
Lucio Lelii 5 years ago
parent af91624406
commit 6b0b45c988

@ -15,11 +15,13 @@
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
<attribute name="test" value="true"/>
</attributes>
</classpathentry>
<classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources">
<attributes>
<attribute name="maven.pomderived" value="true"/>
<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">
@ -30,6 +32,7 @@
<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="output" path="target/classes"/>

@ -5,11 +5,21 @@
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.wst.common.project.facet.core.builder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.wst.validation.validationbuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.m2e.core.maven2Builder</name>
<arguments>
@ -17,7 +27,11 @@
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jem.workbench.JavaEMFNature</nature>
<nature>org.eclipse.wst.common.modulecore.ModuleCoreNature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.eclipse.m2e.core.maven2Nature</nature>
<nature>org.eclipse.wst.common.project.facet.core.nature</nature>
<nature>org.eclipse.wst.jsdt.core.jsNature</nature>
</natures>
</projectDescription>

@ -1,5 +1,8 @@
<ReleaseNotes>
<Changeset component="org.gcube.data-analysis.r-connector.2.1.2" date="2017-03-27">
<Changeset component="org.gcube.data-analysis.r-connector.2.1.4" date="2019-03-27">
<Change>integration with storageHub</Change>
</Changeset>
<Changeset component="org.gcube.data-analysis.r-connector.2.1.3" date="2017-03-27">
<Change>add user script is executed also when configfile.csv is not present</Change>
</Changeset>
<Changeset component="org.gcube.data-analysis.r-connector.2.1.2" date="2017-02-22">

@ -11,6 +11,10 @@
<param-name>addUserScript</param-name>
<param-value>/usr/local/bin/rusersadd</param-value>
</context-param>
<context-param>
<param-name>unmountScript</param-name>
<param-value>/usr/local/bin/rconnector_unmount</param-value>
</context-param>
<context-param>
<param-name>storedKeyPath</param-name>
<param-value>/var/lib/rstudio-server/secure-cookie-key</param-value>

@ -1,9 +1,10 @@
<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>
<groupId>org.gcube.data.analysis</groupId>
<artifactId>r-connector</artifactId>
<version>2.1.3-SNAPSHOT</version>
<version>2.1.4-SNAPSHOT</version>
<name>RConnector</name>
<description>makes R available in the infrastructure</description>
@ -64,7 +65,12 @@
<artifactId>tabulardata-client-library</artifactId>
<version>[2.0.0-SNAPSHOT, 3.0.0-SNAPSHOT)</version>
</dependency>
<dependency>
<groupId>org.gcube.data-access</groupId>
<artifactId>sh-fuse-integration</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
<!-- jersey -->
<dependency>
<groupId>javax.ws.rs</groupId>

@ -1,13 +1,13 @@
package org.gcube.data.analysis.rconnector;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import javax.inject.Singleton;
import org.gcube.common.authorization.library.provider.SecurityTokenProvider;
import org.gcube.common.scope.api.ScopeProvider;
import lombok.extern.slf4j.Slf4j;
@ -21,38 +21,10 @@ public class ConfigFileWriter {
usersHome=usersHome+"/";
File userDir = new File(usersHome+login);
File configFile= new File(userDir, fileName);
executeCommandLine(scriptToExecute,login);
Utils.executeCommandLine(scriptToExecute,login, SecurityTokenProvider.instance.get(), ScopeProvider.instance.get());
return writeFile(info, configFile);
}
private String executeCommandLine(String cmd, String login){
log.debug("executing command "+cmd+" "+login);
Process process = null;
String lastline = "";
try {
ProcessBuilder pb = new ProcessBuilder(cmd, login);
process = pb.start();
try {
process.waitFor();
} catch (InterruptedException e) {
log.warn("interrupt Exception on process",e);
}
BufferedReader br = new BufferedReader(new InputStreamReader(process.getErrorStream()));
String line = br.readLine();
while (line!=null){
lastline += line;
line = br.readLine();
}
} catch (IOException e) {
log.error("error executing command line",e);
}
log.debug("command result line is "+lastline);
return lastline;
}
private boolean writeFile(Info info, File pathToFile){
log.debug("writing config file");
StringBuffer sb = new StringBuffer();

@ -1,5 +1,6 @@
package org.gcube.data.analysis.rconnector;
import javax.inject.Inject;
import javax.servlet.ServletContext;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
@ -10,21 +11,39 @@ import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import org.gcube.common.authorization.library.provider.AuthorizationProvider;
import lombok.extern.slf4j.Slf4j;
@Path("disconnect")
@Slf4j
public class DisconnectResource {
@Context ServletContext context;
@Inject
InfoRetriever infoRetriever;
@GET
@Produces(MediaType.TEXT_HTML)
public Response disconnect(@Context HttpServletRequest req) {
log.info("disconnect called ");
String rStudioServerAddress = context==null?"":context.getInitParameter("rStudioAddress");
log.info(rStudioServerAddress);
String scriptToExecute = context.getInitParameter("unmountScript");
String login = null;
for (Cookie cookie : req.getCookies())
if (cookie.getName().equals("user-id"))
login = cookie.getValue();
if (login==null)
return Response.serverError().build();
try{
Utils.executeCommandLine(scriptToExecute, login);
boolean found = false;
for (Cookie cookie : req.getCookies())
if (cookie.getName().equals("user-id")){
@ -39,8 +58,8 @@ public class DisconnectResource {
).build();
else return Response.ok(context.getClassLoader().getResourceAsStream("inactivesession.html")).build();
}catch(Exception e){
e.printStackTrace();
return null;
log.error("erorr disconnecting from Rstudio",e);
return Response.serverError().build();
}
}

@ -10,8 +10,6 @@ import java.util.regex.Pattern;
import javax.inject.Inject;
import javax.inject.Singleton;
import lombok.extern.slf4j.Slf4j;
import org.gcube.common.authorization.library.provider.SecurityTokenProvider;
import org.gcube.common.database.DatabaseEndpointIdentifier;
import org.gcube.common.database.DatabaseProvider;
@ -25,6 +23,8 @@ import org.gcube.data.analysis.tabulardata.model.metadata.common.NamesMetadata;
import org.gcube.data.analysis.tabulardata.model.metadata.table.DatasetViewTableMetadata;
import org.gcube.data.analysis.tabulardata.model.table.Table;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@Singleton
public class InfoRetriever {
@ -32,7 +32,6 @@ public class InfoRetriever {
@Inject
DatabaseProvider databaseProvider;
@SuppressWarnings("unchecked")
public Info retrieve(String userName, Long tabularResourceId){
try {

@ -1,9 +1,11 @@
package org.gcube.data.analysis.rconnector;
import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.net.URLEncoder;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Locale;
@ -20,11 +22,12 @@ import javax.ws.rs.core.NewCookie;
import javax.ws.rs.core.Response;
import javax.xml.bind.DatatypeConverter;
import lombok.extern.slf4j.Slf4j;
import org.gcube.common.authorization.library.provider.AuthorizationProvider;
import org.gcube.common.authorization.library.provider.SecurityTokenProvider;
import org.gcube.common.scope.api.ScopeProvider;
import org.gcube.data.access.storagehub.fs.StorageHubFS;
import lombok.extern.slf4j.Slf4j;
@Path("connect/")
@Slf4j
@ -35,85 +38,89 @@ public class Resource {
@Inject
InfoRetriever infoRetriever;
@Context ServletContext context;
@Path("/{trId}")
@GET
public Response connect(@PathParam("trId") Long tabularResourceId) {
log.info("connect called with user {} and trID {} in scope {}",AuthorizationProvider.instance.get().getClient().getId(), tabularResourceId, ScopeProvider.instance.get());
String login = AuthorizationProvider.instance.get().getClient().getId();
String usersHome = context.getInitParameter("usersHome");
String filename = context.getInitParameter("filename");
String scriptToExecute = context.getInitParameter("addUserScript");
if (ScopeProvider.instance.get()==null || AuthorizationProvider.instance.get().getClient().getId() == null || tabularResourceId ==null ) return Response.serverError().build();
if (ScopeProvider.instance.get()==null || login == null || tabularResourceId ==null ) return Response.serverError().build();
Info info;
try{
info = infoRetriever.retrieve(AuthorizationProvider.instance.get().getClient().getId(), tabularResourceId);
info = infoRetriever.retrieve(login, tabularResourceId);
log.debug("retrieved info: "+info);
}catch(Exception e){
log.error("error connecting to r",e);
return Response.serverError().build();
}
if (!writer.write(info, AuthorizationProvider.instance.get().getClient().getId(), usersHome, filename, scriptToExecute)) return Response.serverError().build();
return createResponse(AuthorizationProvider.instance.get().getClient().getId());
if (!writer.write(info, login, usersHome, filename, scriptToExecute)) return Response.serverError().build();
return createResponse(login);
}
@GET
public Response connect() {
log.info("connect called with user {} in scope {}",AuthorizationProvider.instance.get().getClient().getId(), ScopeProvider.instance.get());
String login = AuthorizationProvider.instance.get().getClient().getId();
String usersHome = context.getInitParameter("usersHome");
String filename = context.getInitParameter("filename");
String scriptToExecute = context.getInitParameter("addUserScript");
if (AuthorizationProvider.instance.get().getClient().getId() == null ) return Response.serverError().build();
if (login == null ) return Response.serverError().build();
Info info = new Info();
info.setUsername(AuthorizationProvider.instance.get().getClient().getId());
info.setUsername(login);
info.setToken(SecurityTokenProvider.instance.get());
if (!writer.write(info, AuthorizationProvider.instance.get().getClient().getId(), usersHome, filename, scriptToExecute)) return Response.serverError().build();
if (!writer.write(info, login, usersHome, filename, scriptToExecute)) return Response.serverError().build();
return createResponse(AuthorizationProvider.instance.get().getClient().getId());
}
private Response createResponse(String userName){
try{
String keyFilePath = context.getInitParameter("storedKeyPath");
String rStudioServerAddress = context.getInitParameter("rStudioAddress");
log.debug("key file path: "+keyFilePath);
log.debug("rstudio server address: "+rStudioServerAddress);
Calendar now = Calendar.getInstance();
now.add(Calendar.YEAR, 10);
now.add(Calendar.DAY_OF_YEAR, -1);
SimpleDateFormat sdf = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.ENGLISH);
String format = sdf.format(now.getTime());
File keyFile = new File(keyFilePath);
if (!keyFile.exists())
return Response.serverError().build();
byte[] keyByte = Files.readAllBytes(keyFile.toPath());
SecretKeySpec keySpec = new SecretKeySpec(keyByte,
"HmacSHA256");
"HmacSHA256");
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(keySpec);
byte[] result = mac.doFinal((userName+format).getBytes());
String encoded = URLEncoder.encode(DatatypeConverter.printBase64Binary(result));
String cookieValue = userName+"|"+URLEncoder.encode(format).replaceAll("\\+", "%20")+"|"+encoded;
NewCookie cookie = new NewCookie("user-id",
cookieValue,
"/", rStudioServerAddress, "", -1, false, true );
return Response.seeOther(new URI("http://"+rStudioServerAddress))
.cookie(cookie).build();
}catch(Exception e){
log.error("error creating response", e);
return Response.serverError().build();}
}
}

@ -0,0 +1,43 @@
package org.gcube.data.analysis.rconnector;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Utils {
private static Logger log = LoggerFactory.getLogger(Utils.class);
protected static String executeCommandLine(String ... args){
log.debug("executing command {}",Arrays.asList(args));
Process process = null;
String lastline = "";
try {
ProcessBuilder pb = new ProcessBuilder(args);
process = pb.start();
try {
process.waitFor();
} catch (InterruptedException e) {
log.warn("interrupt Exception on process",e);
}
BufferedReader br = new BufferedReader(new InputStreamReader(process.getErrorStream()));
String line = br.readLine();
while (line!=null){
lastline += line;
line = br.readLine();
}
} catch (IOException e) {
log.error("error executing command line",e);
}
log.debug("command result line is {} ",lastline);
return lastline;
}
}

@ -1,5 +1,3 @@
<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd">
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/beans_1_0.xsd">
</beans>
Loading…
Cancel
Save