QuickCloud: copy authorization code from ConsoleProxyManagerImpl

Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/e2fdd720
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/e2fdd720
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/e2fdd720

Branch: refs/heads/quickcloud
Commit: e2fdd720c0a75f0c7a9f1c6a491bebc41cb87ba9
Parents: 5391852
Author: Chiradeep Vittal <chirad...@apache.org>
Authored: Tue Mar 26 10:05:06 2013 -0700
Committer: Chiradeep Vittal <chirad...@apache.org>
Committed: Tue Mar 26 10:05:06 2013 -0700

----------------------------------------------------------------------
 .../consoleproxy/StaticConsoleProxyManager.java    |  268 ++++++++++++++-
 1 files changed, 257 insertions(+), 11 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/e2fdd720/server/src/com/cloud/consoleproxy/StaticConsoleProxyManager.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/consoleproxy/StaticConsoleProxyManager.java 
b/server/src/com/cloud/consoleproxy/StaticConsoleProxyManager.java
index 3ba98a9..04e6f24 100755
--- a/server/src/com/cloud/consoleproxy/StaticConsoleProxyManager.java
+++ b/server/src/com/cloud/consoleproxy/StaticConsoleProxyManager.java
@@ -16,29 +16,74 @@
 // under the License.
 package com.cloud.consoleproxy;
 
+
+import java.util.Date;
 import java.util.List;
 import java.util.Map;
+import java.util.Random;
+import java.util.UUID;
 
 import javax.ejb.Local;
 import javax.inject.Inject;
 import javax.naming.ConfigurationException;
 
-import org.springframework.stereotype.Component;
+import org.apache.log4j.Logger;
 
+import com.cloud.agent.api.AgentControlAnswer;
+import com.cloud.agent.api.Answer;
+import com.cloud.agent.api.ConsoleAccessAuthenticationAnswer;
+import com.cloud.agent.api.ConsoleAccessAuthenticationCommand;
+import com.cloud.agent.api.GetVncPortAnswer;
+import com.cloud.agent.api.GetVncPortCommand;
+import com.cloud.agent.api.StartupCommand;
+import com.cloud.agent.api.StartupProxyCommand;
+import com.cloud.agent.api.proxy.StartConsoleProxyAgentHttpHandlerCommand;
+import com.cloud.configuration.Config;
 import com.cloud.configuration.dao.ConfigurationDao;
+import com.cloud.exception.AgentUnavailableException;
+import com.cloud.exception.OperationTimedoutException;
 import com.cloud.host.Host.Type;
 import com.cloud.host.HostVO;
+import com.cloud.host.dao.HostDao;
 import com.cloud.info.ConsoleProxyInfo;
+import com.cloud.keystore.KeystoreDao;
+import com.cloud.keystore.KeystoreManager;
 import com.cloud.resource.ResourceManager;
+import com.cloud.resource.ResourceStateAdapter;
+import com.cloud.resource.ServerResource;
+import com.cloud.resource.UnableDeleteHostException;
+import com.cloud.servlet.ConsoleProxyServlet;
+import com.cloud.utils.NumbersUtil;
+import com.cloud.utils.Ternary;
 import com.cloud.vm.VMInstanceVO;
+import com.cloud.vm.VirtualMachine;
 import com.cloud.vm.dao.ConsoleProxyDao;
+import com.cloud.vm.dao.VMInstanceDao;
 
 @Local(value={ConsoleProxyManager.class})
-public class StaticConsoleProxyManager extends AgentBasedConsoleProxyManager 
implements ConsoleProxyManager {
-    String _ip = null;
-    @Inject ConsoleProxyDao _proxyDao;
-    @Inject ResourceManager _resourceMgr;
-    @Inject ConfigurationDao _configDao;
+public class StaticConsoleProxyManager extends AgentBasedConsoleProxyManager 
implements ConsoleProxyManager,
+        ResourceStateAdapter {
+    private static final Logger s_logger = 
Logger.getLogger(StaticConsoleProxyManager.class);
+
+    @Inject
+    ConsoleProxyDao _proxyDao;
+    @Inject
+    ResourceManager _resourceMgr;
+    @Inject
+    ConfigurationDao _configDao;
+    @Inject
+    private VMInstanceDao _instanceDao;
+    @Inject
+    KeystoreDao _ksDao;
+    @Inject
+    private KeystoreManager _ksMgr;
+    @Inject
+    private HostDao _hostDao;
+    private final Random _random = new Random(System.currentTimeMillis());
+    private String _hashKey;
+    private String _ip = null;
+
+
 
     @Override
     protected HostVO findHost(VMInstanceVO vm) {
@@ -50,20 +95,221 @@ public class StaticConsoleProxyManager extends 
AgentBasedConsoleProxyManager imp
 
     @Override
     public ConsoleProxyInfo assignProxy(long dataCenterId, long userVmId) {
-        return new ConsoleProxyInfo(false, _ip, _consoleProxyPort, 
_consoleProxyUrlPort, _consoleProxyUrlDomain);
+        return new ConsoleProxyInfo(_sslEnabled, _ip, _consoleProxyPort, 
_consoleProxyUrlPort, _consoleProxyUrlDomain);
     }
 
     @Override
     public boolean configure(String name, Map<String, Object> params) throws 
ConfigurationException {
         super.configure(name, params);
-
-        Map<String, String> dbParams = 
_configDao.getConfiguration("ManagementServer", params);
-
-        _ip = dbParams.get("public.ip");
+        _ip = _configDao.getValue("consoleproxy.static.publicIp");
         if (_ip == null) {
             _ip = "127.0.0.1";
         }
 
+
+        String value = (String) params.get("consoleproxy.sslEnabled");
+        if (value != null && value.equalsIgnoreCase("true")) {
+            _sslEnabled = true;
+        }
+        int defaultPort = 8088;
+        if (_sslEnabled)
+            defaultPort = 8443;
+        _consoleProxyUrlPort = 
NumbersUtil.parseInt(_configDao.getValue("consoleproxy.static.port"), 
defaultPort);
+
+        
_resourceMgr.registerResourceStateAdapter(this.getClass().getSimpleName(), 
this);
+
         return true;
     }
+
+    @Override
+    public HostVO createHostVOForConnectedAgent(HostVO host, StartupCommand[] 
cmd) {
+        if (!(cmd[0] instanceof StartupProxyCommand)) {
+            return null;
+        }
+
+        host.setType(com.cloud.host.Host.Type.ConsoleProxy);
+        return host;
+    }
+
+    @Override
+    public HostVO createHostVOForDirectConnectAgent(HostVO host, 
StartupCommand[] startup, ServerResource resource,
+            Map<String, String> details, List<String> hostTags) {
+        return null;
+    }
+
+    @Override
+    public DeleteHostAnswer deleteHost(HostVO host, boolean isForced, boolean 
isForceDeleteStorage)
+            throws UnableDeleteHostException {
+        return null;
+    }
+
+    @Override
+    public void startAgentHttpHandlerInVM(StartupProxyCommand startupCmd) {
+        StartConsoleProxyAgentHttpHandlerCommand cmd = null;
+        if (_configDao.isPremium()) {
+            String storePassword = String.valueOf(_random.nextLong());
+            byte[] ksBits =
+                    
_ksMgr.getKeystoreBits(ConsoleProxyManager.CERTIFICATE_NAME, 
ConsoleProxyManager.CERTIFICATE_NAME,
+                            storePassword);
+
+            assert (ksBits != null);
+            if (ksBits == null) {
+                s_logger.error("Could not find and construct a valid SSL 
certificate");
+            }
+            cmd = new StartConsoleProxyAgentHttpHandlerCommand(ksBits, 
storePassword);
+            cmd.setEncryptorPassword(getHashKey());
+        } else {
+            cmd = new StartConsoleProxyAgentHttpHandlerCommand();
+            cmd.setEncryptorPassword(getHashKey());
+        }
+        HostVO consoleProxyHost = findConsoleProxyHost(startupCmd.getGuid());
+
+        Answer answer;
+        try {
+            answer = _agentMgr.send(consoleProxyHost.getId(), cmd);
+            if (answer == null || !answer.getResult()) {
+                s_logger.error("Console proxy agent reported that it failed to 
execute http handling startup command");
+            } else {
+                s_logger.info("Successfully sent out command to start HTTP 
handling in console proxy agent");
+            }
+        } catch (AgentUnavailableException e) {
+            s_logger.error("Failed to send http start up command to console 
proxy due to ", e);
+        } catch (OperationTimedoutException e) {
+            s_logger.error("Failed to send http start up command to console 
proxy due to ", e);
+        }
+
+
+    }
+
+    private HostVO findConsoleProxyHost(String guid) {
+        return _hostDao.findByGuid(guid);
+    }
+
+    public String getHashKey() {
+        // although we may have race conditioning here, database transaction
+        // serialization should
+        // give us the same key
+        if (_hashKey == null) {
+            _hashKey =
+                    _configDao.getValueAndInitIfNotExist(Config.HashKey.key(), 
Config.HashKey.getCategory(), UUID
+                            .randomUUID().toString());
+        }
+        return _hashKey;
+    }
+
+    public AgentControlAnswer 
onConsoleAccessAuthentication(ConsoleAccessAuthenticationCommand cmd) {
+        Long vmId = null;
+
+        String ticketInUrl = cmd.getTicket();
+        if (ticketInUrl == null) {
+            s_logger.error("Access ticket could not be found, you could be 
running an old version of console proxy. vmId: "
+                    + cmd.getVmId());
+            return new ConsoleAccessAuthenticationAnswer(cmd, false);
+        }
+
+        if (s_logger.isDebugEnabled()) {
+            s_logger.debug("Console authentication. Ticket in url for " + 
cmd.getHost() + ":" + cmd.getPort() + "-"
+                    + cmd.getVmId() + " is " + ticketInUrl);
+        }
+
+        if (!cmd.isReauthenticating()) {
+            String ticket =
+                    ConsoleProxyServlet.genAccessTicket(cmd.getHost(), 
cmd.getPort(), cmd.getSid(), cmd.getVmId());
+            if (s_logger.isDebugEnabled()) {
+                s_logger.debug("Console authentication. Ticket in 1 minute 
boundary for " + cmd.getHost() + ":"
+                        + cmd.getPort() + "-" + cmd.getVmId() + " is " + 
ticket);
+            }
+
+            if (!ticket.equals(ticketInUrl)) {
+                Date now = new Date();
+                // considering of minute round-up
+                String minuteEarlyTicket =
+                        ConsoleProxyServlet.genAccessTicket(cmd.getHost(), 
cmd.getPort(), cmd.getSid(), cmd.getVmId(),
+                                new Date(now.getTime() - 60 * 1000));
+
+                if (s_logger.isDebugEnabled()) {
+                    s_logger.debug("Console authentication. Ticket in 2-minute 
boundary for " + cmd.getHost() + ":"
+                            + cmd.getPort() + "-" + cmd.getVmId() + " is " + 
minuteEarlyTicket);
+                }
+
+                if (!minuteEarlyTicket.equals(ticketInUrl)) {
+                    s_logger.error("Access ticket expired or has been 
modified. vmId: " + cmd.getVmId()
+                            + "ticket in URL: " + ticketInUrl + ", tickets to 
check against: " + ticket + ","
+                            + minuteEarlyTicket);
+                    return new ConsoleAccessAuthenticationAnswer(cmd, false);
+                }
+            }
+        }
+
+        if (cmd.getVmId() != null && cmd.getVmId().isEmpty()) {
+            if (s_logger.isDebugEnabled()) {
+                s_logger.debug("Invalid vm id sent from proxy(happens when 
proxy session has terminated)");
+            }
+            return new ConsoleAccessAuthenticationAnswer(cmd, false);
+        }
+
+        VirtualMachine vm = _instanceDao.findByUuid(cmd.getVmId());
+        if (vm == null) {
+            vm = _instanceDao.findById(Long.parseLong(cmd.getVmId()));
+        }
+        if (vm == null) {
+            s_logger.error("Invalid vm id " + cmd.getVmId() + " sent from 
console access authentication");
+            return new ConsoleAccessAuthenticationAnswer(cmd, false);
+        }
+
+        if (vm.getHostId() == null) {
+            s_logger.warn("VM " + vmId + " lost host info, failed 
authentication request");
+            return new ConsoleAccessAuthenticationAnswer(cmd, false);
+        }
+
+        HostVO host = _hostDao.findById(vm.getHostId());
+        if (host == null) {
+            s_logger.warn("VM " + vmId + "'s host does not exist, fail 
authentication request");
+            return new ConsoleAccessAuthenticationAnswer(cmd, false);
+        }
+
+        String sid = cmd.getSid();
+        if (sid == null || !sid.equals(vm.getVncPassword())) {
+            s_logger.warn("sid " + sid + " in url does not match stored sid " 
+ vm.getVncPassword());
+            return new ConsoleAccessAuthenticationAnswer(cmd, false);
+        }
+
+        if (cmd.isReauthenticating()) {
+            ConsoleAccessAuthenticationAnswer authenticationAnswer = new 
ConsoleAccessAuthenticationAnswer(cmd, true);
+            authenticationAnswer.setReauthenticating(true);
+
+            s_logger.info("Re-authentication request, ask host " + 
vm.getHostId() + " for new console info");
+            GetVncPortAnswer answer =
+                    (GetVncPortAnswer) _agentMgr.easySend(vm.getHostId(),
+                            new GetVncPortCommand(vm.getId(), 
vm.getInstanceName()));
+
+            if (answer != null && answer.getResult()) {
+                Ternary<String, String, String> parsedHostInfo = 
ConsoleProxyServlet.parseHostInfo(answer.getAddress());
+
+                if (parsedHostInfo.second() != null && parsedHostInfo.third() 
!= null) {
+
+                    s_logger.info("Re-authentication result. vm: " + 
vm.getId() + ", tunnel url: "
+                            + parsedHostInfo.second() + ", tunnel session: " + 
parsedHostInfo.third());
+
+                    authenticationAnswer.setTunnelUrl(parsedHostInfo.second());
+                    
authenticationAnswer.setTunnelSession(parsedHostInfo.third());
+                } else {
+                    s_logger.info("Re-authentication result. vm: " + 
vm.getId() + ", host address: "
+                            + parsedHostInfo.first() + ", port: " + 
answer.getPort());
+
+                    authenticationAnswer.setHost(parsedHostInfo.first());
+                    authenticationAnswer.setPort(answer.getPort());
+                }
+            } else {
+                s_logger.warn("Re-authentication request failed");
+
+                authenticationAnswer.setSuccess(false);
+            }
+
+            return authenticationAnswer;
+        }
+
+        return new ConsoleAccessAuthenticationAnswer(cmd, true);
+    }
+
 }

Reply via email to