nvazquez commented on code in PR #6577:
URL: https://github.com/apache/cloudstack/pull/6577#discussion_r931173846


##########
server/src/main/java/com/cloud/consoleproxy/ConsoleAccessManagerImpl.java:
##########
@@ -0,0 +1,459 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package com.cloud.consoleproxy;
+
+import com.cloud.agent.AgentManager;
+import com.cloud.agent.api.Answer;
+import com.cloud.agent.api.GetVmVncTicketAnswer;
+import com.cloud.agent.api.GetVmVncTicketCommand;
+import com.cloud.exception.AgentUnavailableException;
+import com.cloud.exception.OperationTimedoutException;
+import com.cloud.host.HostVO;
+import com.cloud.hypervisor.Hypervisor;
+import com.cloud.resource.ResourceState;
+import com.cloud.server.ManagementServer;
+import com.cloud.servlet.ConsoleProxyClientParam;
+import com.cloud.servlet.ConsoleProxyPasswordBasedEncryptor;
+import com.cloud.storage.GuestOSVO;
+import com.cloud.user.Account;
+import com.cloud.user.AccountManager;
+import com.cloud.uservm.UserVm;
+import com.cloud.utils.Pair;
+import com.cloud.utils.Ternary;
+import com.cloud.utils.component.ManagerBase;
+import com.cloud.utils.db.EntityManager;
+import com.cloud.utils.exception.CloudRuntimeException;
+import com.cloud.vm.UserVmDetailVO;
+import com.cloud.vm.VirtualMachine;
+import com.cloud.vm.VirtualMachineManager;
+import com.cloud.vm.VmDetailConstants;
+import com.cloud.vm.dao.UserVmDetailsDao;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import org.apache.cloudstack.consoleproxy.ConsoleAccessManager;
+import org.apache.cloudstack.framework.security.keys.KeysManager;
+import org.apache.commons.codec.binary.Base64;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.log4j.Logger;
+
+import javax.crypto.Mac;
+import javax.crypto.spec.SecretKeySpec;
+import javax.inject.Inject;
+import javax.naming.ConfigurationException;
+import java.net.InetAddress;
+import java.util.Date;
+import java.util.Map;
+
+public class ConsoleAccessManagerImpl extends ManagerBase implements 
ConsoleAccessManager {
+
+    @Inject
+    private AccountManager _accountMgr;
+    @Inject
+    private VirtualMachineManager _vmMgr;
+    @Inject
+    private ManagementServer _ms;
+    @Inject
+    private EntityManager _entityMgr;
+    @Inject
+    private UserVmDetailsDao _userVmDetailsDao;
+    @Inject
+    private KeysManager _keysMgr;
+    @Inject
+    private AgentManager agentManager;
+
+    private static KeysManager s_keysMgr;
+    private final Gson _gson = new GsonBuilder().create();
+
+    public static final Logger s_logger = 
Logger.getLogger(ConsoleAccessManagerImpl.class.getName());
+
+    @Override
+    public boolean configure(String name, Map<String, Object> params) throws 
ConfigurationException {
+        s_keysMgr = _keysMgr;
+        return super.configure(name, params);
+    }
+
+    @Override
+    public Pair<Boolean, String> generateConsoleUrl(Long vmId) {
+        try {
+            if (_accountMgr == null || _vmMgr == null || _ms == null) {
+                return new Pair<>(false, "Service is not ready");
+            }
+
+            if (_keysMgr.getHashKey() == null) {
+                String msg = "Console/thumbnail access denied. Ticket service 
is not ready yet";
+                s_logger.debug(msg);
+                return new Pair<>(false, msg);
+            }
+
+            String userId = null;
+            String account = null;
+            Account accountObj = null;
+
+//            Map<String, Object[]> params = new HashMap<String, Object[]>();
+//            params.putAll(req.getParameterMap());
+//
+//            HttpSession session = req.getSession(false);
+//            if (session == null) {
+//                if (verifyRequest(params)) {
+//                    userId = (String)params.get("userid")[0];
+//                    account = (String)params.get("account")[0];
+//                    accountObj = (Account)params.get("accountobj")[0];
+//                } else {
+//                    s_logger.debug("Invalid web session or API key in 
request, reject console/thumbnail access");
+//                    sendResponse(resp, "Access denied. Invalid web session 
or API key in request");
+//                    return;
+//                }
+//            } else {
+//                // adjust to latest API refactoring changes
+//                if (session.getAttribute("userid") != null) {
+//                    userId = 
((Long)session.getAttribute("userid")).toString();
+//                }
+//
+//                accountObj = (Account)session.getAttribute("accountobj");
+//                if (accountObj != null) {
+//                    account = "" + accountObj.getId();
+//                }
+//            }
+
+//            // Do a sanity check here to make sure the user hasn't already 
been deleted
+//            if ((userId == null) || (account == null) || (accountObj == 
null) || !verifyUser(Long.valueOf(userId))) {
+//                s_logger.debug("Invalid user/account, reject 
console/thumbnail access");
+//                sendResponse(resp, "Access denied. Invalid or inconsistent 
account is found");
+//                return;
+//            }
+//
+//            String cmd = req.getParameter("cmd");
+//            if (cmd == null || !isValidCmd(cmd)) {
+//                s_logger.debug("invalid console servlet command: " + cmd);
+//                sendResponse(resp, "");
+//                return;
+//            }
+//
+//            String vmIdString = req.getParameter("vm");
+            VirtualMachine vm = _entityMgr.findById(VirtualMachine.class, 
vmId);
+            if (vm == null) {
+                s_logger.info("invalid console servlet command parameter: " + 
vmId);
+                return new Pair<>(false, "Cannot find VM with ID " + vmId);
+            }
+
+//            if (!checkSessionPermision(req, vmId, accountObj)) {
+//                sendResponse(resp, "Permission denied");
+//                return;
+//            }
+
+//            if (cmd.equalsIgnoreCase("thumbnail")) {
+//                handleThumbnailRequest(req, resp, vmId);
+//            } else if (cmd.equalsIgnoreCase("access")) {
+//                handleAccessRequest(req, resp, vmId);
+//            } else {
+//                handleAuthRequest(req, resp, vmId);
+//            }
+            return new Pair<>(true, generateAccessUrl(vmId));
+        } catch (Throwable e) {
+            s_logger.error("Unexepected exception in ConsoleProxyServlet", e);
+            return new Pair<>(false, "Server Internal Error: " + 
e.getMessage());
+        }
+    }
+
+    private String generateAccessUrl(Long vmId) {
+        VirtualMachine vm = _vmMgr.findById(vmId);
+        String msg;
+        if (vm == null) {
+            msg = "VM " + vmId + " does not exist, sending blank response for 
console access request";
+            s_logger.warn(msg);
+            throw new CloudRuntimeException(msg);
+        }
+
+        if (vm.getHostId() == null) {
+            msg = "VM " + vmId + " lost host info, sending blank response for 
console access request";
+            s_logger.warn(msg);
+            throw new CloudRuntimeException(msg);
+        }
+
+        HostVO host = _ms.getHostBy(vm.getHostId());
+        if (host == null) {
+            msg = "VM " + vmId + "'s host does not exist, sending blank 
response for console access request";
+            s_logger.warn(msg);
+            throw new CloudRuntimeException(msg);
+        }
+
+        if (Hypervisor.HypervisorType.LXC.equals(vm.getHypervisorType())) {
+            throw new CloudRuntimeException("Console access is not supported 
for LXC");
+        }
+
+        String rootUrl = _ms.getConsoleAccessUrlRoot(vmId);
+        if (rootUrl == null) {
+            throw new CloudRuntimeException("Console access will be ready in a 
few minutes. Please try it again later.");
+        }
+
+        String vmName = vm.getHostName();
+        if (vm.getType() == VirtualMachine.Type.User) {
+            UserVm userVm = _entityMgr.findById(UserVm.class, vmId);
+            String displayName = userVm.getDisplayName();
+            if (displayName != null && !displayName.isEmpty() && 
!displayName.equals(vmName)) {
+                vmName += "(" + displayName + ")";
+            }
+        }
+
+//        InetAddress remoteAddress = null;
+//        try {
+//            remoteAddress = ApiServlet.getClientAddress(req);
+//        } catch (UnknownHostException e) {
+//            s_logger.warn("UnknownHostException when trying to lookup remote 
IP-Address. This should never happen. Blocking request.", e);
+//        }
+
+        String url = composeConsoleAccessUrl(rootUrl, vm, host, null);
+        s_logger.debug("The console URL is: " + url);
+        return url;
+    }
+
+    public static final String escapeHTML(String content) {
+        if (content == null || content.isEmpty())
+            return content;
+
+        StringBuilder sb = new StringBuilder();
+        for (int i = 0; i < content.length(); i++) {
+            char c = content.charAt(i);
+            switch (c) {
+                case '<':
+                    sb.append("&lt;");
+                    break;
+                case '>':
+                    sb.append("&gt;");
+                    break;
+                case '&':
+                    sb.append("&amp;");
+                    break;
+                case '"':
+                    sb.append("&quot;");
+                    break;
+                case ' ':
+                    sb.append("&nbsp;");
+                    break;
+                default:
+                    sb.append(c);
+                    break;
+            }
+        }
+        return sb.toString();
+    }
+
+    private String composeConsoleAccessUrl(String rootUrl, VirtualMachine vm, 
HostVO hostVo, InetAddress addr) {

Review Comment:
   Yes, the goal is to move the code away from the servlet in favour of the API 
implementation. Please note this PR is still in progress, will be polishing it



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to