mirror of https://github.com/apache/cloudstack.git
Complete XenServer Secure Console proxy implementation
This commit is contained in:
parent
f34c84c68f
commit
f38ba2efbe
|
|
@ -365,14 +365,10 @@ public class ConsoleProxy {
|
|||
} else if (!viewer.isFrontEndAlive()) {
|
||||
s_logger.info("The rfb thread died, reinitializing the viewer " + viewer);
|
||||
viewer.initClient(param);
|
||||
|
||||
reportLoadChange = true;
|
||||
} else if (!param.getClientHostPassword().equals(viewer.getClientHostPassword())) {
|
||||
s_logger.warn("Bad sid detected(VNC port may be reused). sid in session: " + viewer.getClientHostPassword()
|
||||
+ ", sid in request: " + param.getClientHostPassword());
|
||||
viewer.initClient(param);
|
||||
|
||||
reportLoadChange = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -404,12 +400,10 @@ public class ConsoleProxy {
|
|||
s_logger.info("The rfb thread died, reinitializing the viewer " +
|
||||
viewer);
|
||||
viewer.initClient(param);
|
||||
reportLoadChange = true;
|
||||
} else if (!param.getClientHostPassword().equals(viewer.getClientHostPassword())) {
|
||||
s_logger.warn("Bad sid detected(VNC port may be reused). sid in session: "
|
||||
+ viewer.getClientHostPassword() + ", sid in request: " + param.getClientHostPassword());
|
||||
viewer.initClient(param);
|
||||
reportLoadChange = true;
|
||||
} else {
|
||||
if(ajaxSession == null || ajaxSession.isEmpty())
|
||||
authenticationExternally(param);
|
||||
|
|
|
|||
|
|
@ -71,6 +71,8 @@ public class ConsoleProxyAjaxHandler implements HttpHandler {
|
|||
String ticket = queryMap.get("ticket");
|
||||
String ajaxSessionIdStr = queryMap.get("sess");
|
||||
String eventStr = queryMap.get("event");
|
||||
String console_url = queryMap.get("consoleurl");
|
||||
String console_host_session = queryMap.get("sessionref");
|
||||
|
||||
if(tag == null)
|
||||
tag = "";
|
||||
|
|
@ -116,6 +118,8 @@ public class ConsoleProxyAjaxHandler implements HttpHandler {
|
|||
param.setClientHostPassword(sid);
|
||||
param.setClientTag(tag);
|
||||
param.setTicket(ticket);
|
||||
param.setClientTunnelUrl(console_url);
|
||||
param.setClientTunnelSession(console_host_session);
|
||||
|
||||
viewer = ConsoleProxy.getAjaxVncViewer(param, ajaxSessionIdStr);
|
||||
} catch(Exception e) {
|
||||
|
|
@ -184,6 +188,11 @@ public class ConsoleProxyAjaxHandler implements HttpHandler {
|
|||
String name = param.split("=")[0];
|
||||
String value = param.split("=")[1];
|
||||
map.put(name, value);
|
||||
} else if (paramTokens.length == 3) {
|
||||
// very ugly, added for Xen tunneling url
|
||||
String name = paramTokens[0];
|
||||
String value = paramTokens[1] + "=" + paramTokens[2];
|
||||
map.put(name, value);
|
||||
} else {
|
||||
if(s_logger.isDebugEnabled())
|
||||
s_logger.debug("Invalid paramemter in URL found. param: " + param);
|
||||
|
|
|
|||
|
|
@ -62,8 +62,6 @@ public class ConsoleProxyAjaxImageHandler implements HttpHandler {
|
|||
String tag = queryMap.get("tag");
|
||||
String ticket = queryMap.get("ticket");
|
||||
String keyStr = queryMap.get("key");
|
||||
String console_url = queryMap.get("consoleurl");
|
||||
String console_host_session = queryMap.get("sessionref");
|
||||
int key = 0;
|
||||
|
||||
if(tag == null)
|
||||
|
|
|
|||
|
|
@ -25,6 +25,9 @@ public class ConsoleProxyClientParam {
|
|||
private String clientTag;
|
||||
private String ticket;
|
||||
|
||||
private String clientTunnelUrl;
|
||||
private String clientTunnelSession;
|
||||
|
||||
public ConsoleProxyClientParam() {
|
||||
clientHostPort = 0;
|
||||
}
|
||||
|
|
@ -69,6 +72,22 @@ public class ConsoleProxyClientParam {
|
|||
this.ticket = ticket;
|
||||
}
|
||||
|
||||
public String getClientTunnelUrl() {
|
||||
return clientTunnelUrl;
|
||||
}
|
||||
|
||||
public void setClientTunnelUrl(String clientTunnelUrl) {
|
||||
this.clientTunnelUrl = clientTunnelUrl;
|
||||
}
|
||||
|
||||
public String getClientTunnelSession() {
|
||||
return clientTunnelSession;
|
||||
}
|
||||
|
||||
public void setClientTunnelSession(String clientTunnelSession) {
|
||||
this.clientTunnelSession = clientTunnelSession;
|
||||
}
|
||||
|
||||
public String getClientMapKey() {
|
||||
return clientHostAddress + ":" + clientHostPort;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -107,8 +107,11 @@ public class ConsoleProxyThumbnailHandler implements HttpHandler {
|
|||
String sid = queryMap.get("sid");
|
||||
String tag = queryMap.get("tag");
|
||||
String ticket = queryMap.get("ticket");
|
||||
String console_url = queryMap.get("consoleurl");
|
||||
String console_host_session = queryMap.get("sessionref");
|
||||
|
||||
if(tag == null)
|
||||
tag = "";
|
||||
tag = "";
|
||||
|
||||
if (ws == null || hs == null || host == null || portStr == null || sid == null ) {
|
||||
throw new IllegalArgumentException();
|
||||
|
|
|
|||
|
|
@ -13,6 +13,8 @@
|
|||
package com.cloud.consoleproxy;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.UnknownHostException;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
|
|
@ -57,15 +59,33 @@ public class ConsoleProxyVncClient extends ConsoleProxyClientBase {
|
|||
this.port = param.getClientHostPort();
|
||||
this.passwordParam = param.getClientHostPassword();
|
||||
this.tag = param.getClientTag();
|
||||
this.ticket = param.getTicket();
|
||||
|
||||
this.ticket = param.getTicket();
|
||||
|
||||
final String tunnelUrl = param.getClientTunnelUrl();
|
||||
final String tunnelSession = param.getClientTunnelSession();
|
||||
|
||||
client = new VncClient(this);
|
||||
worker = new Thread(new Runnable() {
|
||||
public void run() {
|
||||
long startTick = System.currentTimeMillis();
|
||||
while(System.currentTimeMillis() - startTick < 7000) {
|
||||
try {
|
||||
client.connectTo(host, port, passwordParam);
|
||||
try {
|
||||
if(tunnelUrl != null && !tunnelUrl.isEmpty() && tunnelSession != null && !tunnelSession.isEmpty()) {
|
||||
try {
|
||||
URI uri = new URI(tunnelUrl);
|
||||
s_logger.info("Connect to VNC server via tunnel. url: " + tunnelUrl + ", session: " + tunnelSession);
|
||||
client.connectTo(
|
||||
uri.getHost(), uri.getPort(),
|
||||
uri.getPath() + "?" + uri.getQuery(),
|
||||
tunnelSession, "https".equalsIgnoreCase(uri.getScheme()),
|
||||
passwordParam);
|
||||
} catch (URISyntaxException e) {
|
||||
s_logger.warn("Invalid tunnel URL " + tunnelUrl);
|
||||
}
|
||||
} else {
|
||||
s_logger.info("Connect to VNC server directly. host: " + host + ", port: " + port);
|
||||
client.connectTo(host, port, passwordParam);
|
||||
}
|
||||
} catch (UnknownHostException e) {
|
||||
s_logger.error("Unexpected exception: ", e);
|
||||
} catch (IOException e) {
|
||||
|
|
|
|||
|
|
@ -126,10 +126,17 @@ public class VncClient {
|
|||
}
|
||||
|
||||
public void connectTo(String host, int port, String path,
|
||||
String session, boolean useSSL) throws UnknownHostException, IOException {
|
||||
String session, boolean useSSL, String sid) throws UnknownHostException, IOException {
|
||||
if(port < 0) {
|
||||
if(useSSL)
|
||||
port = 443;
|
||||
else
|
||||
port = 80;
|
||||
}
|
||||
|
||||
RawHTTP tunnel = new RawHTTP("CONNECT", host, port, path, session, useSSL);
|
||||
this.socket = tunnel.connect();
|
||||
doConnect("");
|
||||
doConnect(sid);
|
||||
}
|
||||
|
||||
public void connectTo(String host, int port, String password) throws UnknownHostException, IOException {
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ import com.cloud.user.DomainManager;
|
|||
import com.cloud.user.User;
|
||||
import com.cloud.uservm.UserVm;
|
||||
import com.cloud.utils.Pair;
|
||||
import com.cloud.utils.Ternary;
|
||||
import com.cloud.utils.component.ComponentLocator;
|
||||
import com.cloud.utils.db.Transaction;
|
||||
import com.cloud.vm.VMInstanceVO;
|
||||
|
|
@ -283,26 +284,50 @@ public class ConsoleProxyServlet extends HttpServlet {
|
|||
sendResponse(resp, "success");
|
||||
}
|
||||
|
||||
// put the ugly stuff here
|
||||
static private Ternary<String, String, String> parseHostInfo(String hostInfo) {
|
||||
String host = null;
|
||||
String tunnelUrl = null;
|
||||
String tunnelSession = null;
|
||||
|
||||
if(hostInfo != null && hostInfo.startsWith("consoleurl")) {
|
||||
String tokens[] = hostInfo.split("&");
|
||||
|
||||
host = hostInfo.substring(19, hostInfo.indexOf('/', 19)).trim();
|
||||
tunnelUrl = tokens[0].substring("consoleurl=".length());
|
||||
tunnelSession = tokens[1].split("=")[1];
|
||||
} else {
|
||||
host = hostInfo;
|
||||
}
|
||||
|
||||
return new Ternary<String, String, String>(host, tunnelUrl, tunnelSession);
|
||||
}
|
||||
|
||||
private String composeThumbnailUrl(String rootUrl, VMInstanceVO vm, HostVO hostVo, int w, int h) {
|
||||
StringBuffer sb = new StringBuffer(rootUrl);
|
||||
|
||||
String host = hostVo.getPrivateIpAddress();
|
||||
|
||||
Pair<String, Integer> portInfo = _ms.getVncPort(vm);
|
||||
if(portInfo.first() != null) {
|
||||
host = portInfo.first();
|
||||
}
|
||||
Ternary<String, String, String> parsedHostInfo = parseHostInfo(portInfo.first());
|
||||
|
||||
String sid = vm.getVncPassword();
|
||||
String tag = String.valueOf(vm.getId());
|
||||
tag = _identityService.getIdentityUuid("vm_instance", tag);
|
||||
String ticket = genAccessTicket(host, String.valueOf(portInfo.second()), sid, tag);
|
||||
|
||||
sb.append("/getscreen?host=").append(host);
|
||||
sb.append("/getscreen?host=").append(parsedHostInfo.first());
|
||||
sb.append("&port=").append(portInfo.second());
|
||||
sb.append("&sid=").append(sid);
|
||||
sb.append("&w=").append(w).append("&h=").append(h);
|
||||
sb.append("&tag=").append(tag);
|
||||
sb.append("&ticket=").append(ticket);
|
||||
|
||||
if(parsedHostInfo.second() != null && parsedHostInfo.third() != null) {
|
||||
sb.append("&").append("consoleurl=").append(URLEncoder.encode(parsedHostInfo.second()));
|
||||
sb.append("&").append("sessionref=").append(URLEncoder.encode(parsedHostInfo.third()));
|
||||
}
|
||||
|
||||
if(s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Compose thumbnail url: " + sb.toString());
|
||||
}
|
||||
|
|
@ -311,41 +336,28 @@ public class ConsoleProxyServlet extends HttpServlet {
|
|||
|
||||
private String composeConsoleAccessUrl(String rootUrl, VMInstanceVO vm, HostVO hostVo) {
|
||||
StringBuffer sb = new StringBuffer(rootUrl);
|
||||
String[] console_session = null;
|
||||
String console_url = null;
|
||||
String host = hostVo.getPrivateIpAddress();
|
||||
|
||||
Pair<String, Integer> portInfo = _ms.getVncPort(vm);
|
||||
|
||||
s_logger.debug("Port info " + portInfo.first());
|
||||
|
||||
if(portInfo.first() != null) {
|
||||
console_url = host = portInfo.first();
|
||||
}
|
||||
|
||||
System.out.println("Port info " + portInfo.first());
|
||||
if ( console_url !=null && console_url.startsWith("consoleurl")) {
|
||||
console_session = console_url.split("&");
|
||||
host = console_url.substring(19,console_url.indexOf('/', 19)).trim();
|
||||
}
|
||||
if(s_logger.isDebugEnabled())
|
||||
s_logger.debug("Port info " + portInfo.first());
|
||||
|
||||
Ternary<String, String, String> parsedHostInfo = parseHostInfo(portInfo.first());
|
||||
|
||||
|
||||
|
||||
|
||||
String sid = vm.getVncPassword();
|
||||
String tag = String.valueOf(vm.getId());
|
||||
tag = _identityService.getIdentityUuid("vm_instance", tag);
|
||||
String ticket = genAccessTicket(host, String.valueOf(portInfo.second()), sid, tag);
|
||||
|
||||
sb.append("/ajax?host=").append(host);
|
||||
sb.append("/ajax?host=").append(parsedHostInfo.first());
|
||||
sb.append("&port=").append(portInfo.second());
|
||||
sb.append("&sid=").append(sid);
|
||||
sb.append("&tag=").append(tag);
|
||||
sb.append("&ticket=").append(ticket);
|
||||
System.out.println("Port info " + portInfo.first());
|
||||
|
||||
if ( console_session !=null && console_session.length == 2){
|
||||
sb.append("&").append(console_session[0]);
|
||||
sb.append("&").append(console_session[1]);
|
||||
if(parsedHostInfo.second() != null && parsedHostInfo.third() != null) {
|
||||
sb.append("&").append("consoleurl=").append(URLEncoder.encode(parsedHostInfo.second()));
|
||||
sb.append("&").append("sessionref=").append(URLEncoder.encode(parsedHostInfo.third()));
|
||||
}
|
||||
|
||||
// for console access, we need guest OS type to help implement keyboard
|
||||
|
|
|
|||
Loading…
Reference in New Issue