Vitor de Lima has uploaded a new change for review.

Change subject: core, engine: Services for providing info to the Console Proxy
......................................................................

core, engine: Services for providing info to the Console Proxy

This patch creates two services that provide information to the SSH
server that acts as the VirtIO console proxy:

- /services/publickeys: Provides to the authkeys script the list of
  allowed public keys into the SSH server and the respective GUID of
  each allowed user.

- /services/availableconsoles: Lists the available VMs to be accessed
by the user given his GUID and in which host these VMs are located.

In order to protect these services, a BASIC authentication custom
Login Module was created that reads its password from the config
values.

Change-Id: I53c721da21cefcf4069d14c7016b6f7d97f9eac9
Signed-off-by: Vitor de Lima <vdel...@redhat.com>
---
A 
backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/GetAllVmsForAnotherUserQuery.java
M 
backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/config/ConfigValues.java
M 
backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/queries/ConfigurationValues.java
M 
backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/queries/VdcQueryType.java
M backend/manager/modules/services/pom.xml
A 
backend/manager/modules/services/src/main/java/org/ovirt/engine/core/services/GetAvailableConsoles.java
A 
backend/manager/modules/services/src/main/java/org/ovirt/engine/core/services/GetConsolePublicKeys.java
A 
backend/manager/modules/services/src/main/java/org/ovirt/engine/core/services/auth/ConsoleProxyLoginModule.java
A backend/manager/modules/services/src/main/webapp/WEB-INF/jboss-web.xml
M backend/manager/modules/services/src/main/webapp/WEB-INF/web.xml
M packaging/dbscripts/upgrade/pre_upgrade/0000_config.sql
M packaging/services/ovirt-engine/ovirt-engine.xml.in
12 files changed, 352 insertions(+), 0 deletions(-)


  git pull ssh://gerrit.ovirt.org:29418/ovirt-engine refs/changes/87/35887/1

diff --git 
a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/GetAllVmsForAnotherUserQuery.java
 
b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/GetAllVmsForAnotherUserQuery.java
new file mode 100644
index 0000000..db797f7
--- /dev/null
+++ 
b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/GetAllVmsForAnotherUserQuery.java
@@ -0,0 +1,24 @@
+package org.ovirt.engine.core.bll;
+
+import org.ovirt.engine.core.bll.context.EngineContext;
+import org.ovirt.engine.core.common.businessentities.VM;
+import org.ovirt.engine.core.common.queries.IdQueryParameters;
+
+import java.util.List;
+
+public class GetAllVmsForAnotherUserQuery<P extends IdQueryParameters> extends 
QueriesCommandBase<P> {
+    public GetAllVmsForAnotherUserQuery(P parameters) {
+        super(parameters);
+    }
+
+    public GetAllVmsForAnotherUserQuery(P parameters, EngineContext 
engineContext) {
+        super(parameters, engineContext);
+    }
+
+    @Override
+    protected void executeQueryCommand() {
+        List<VM> vmsList = 
getDbFacade().getVmDao().getAllForUser(getParameters().getId());
+
+        getQueryReturnValue().setReturnValue(vmsList);
+    }
+}
diff --git 
a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/config/ConfigValues.java
 
b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/config/ConfigValues.java
index 8c6c3f6..bc8d408 100644
--- 
a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/config/ConfigValues.java
+++ 
b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/config/ConfigValues.java
@@ -859,6 +859,11 @@
     @OptionBehaviourAttribute(behaviour = OptionBehaviour.Password)
     AdminPassword,
 
+    @TypeConverterAttribute(String.class)
+    @DefaultValueAttribute("")
+    @OptionBehaviourAttribute(behaviour = OptionBehaviour.Password)
+    ConsoleProxyPassword,
+
     @Reloadable
     @TypeConverterAttribute(Integer.class)
     @DefaultValueAttribute("30")
diff --git 
a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/queries/ConfigurationValues.java
 
b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/queries/ConfigurationValues.java
index d432749..37908df 100644
--- 
a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/queries/ConfigurationValues.java
+++ 
b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/queries/ConfigurationValues.java
@@ -19,6 +19,7 @@
     // AdUserPassword field format has been changed.
     // AdUserPassword,
     LocalAdminPassword,
+    ConsoleProxyPassword,
     ValidNumOfMonitors(ConfigAuthType.User),
     EnableUSBAsDefault(ConfigAuthType.User),
     SpiceSecureChannels(ConfigAuthType.User),
diff --git 
a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/queries/VdcQueryType.java
 
b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/queries/VdcQueryType.java
index 63ac8f1..e16f310 100644
--- 
a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/queries/VdcQueryType.java
+++ 
b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/queries/VdcQueryType.java
@@ -9,6 +9,7 @@
     GetVmByVmNameForDataCenter(VdcQueryAuthType.User),
     GetAllVms(VdcQueryAuthType.User),
     GetAllVmsForUser(VdcQueryAuthType.User),
+    GetAllVmsForAnotherUser(VdcQueryAuthType.User),
     GetUnregisteredVms,
     GetUnregisteredVmTemplates,
     GetVmsRunningOnOrMigratingToVds,
diff --git a/backend/manager/modules/services/pom.xml 
b/backend/manager/modules/services/pom.xml
index dfc179c..6caaee2 100644
--- a/backend/manager/modules/services/pom.xml
+++ b/backend/manager/modules/services/pom.xml
@@ -21,6 +21,13 @@
     </dependency>
 
     <dependency>
+        <groupId>jboss</groupId>
+        <artifactId>jbosssx</artifactId>
+        <version>3.2.3</version>
+        <scope>provided</scope>
+    </dependency>
+
+    <dependency>
       <groupId>${engine.groupId}</groupId>
       <artifactId>common</artifactId>
       <version>${engine.version}</version>
diff --git 
a/backend/manager/modules/services/src/main/java/org/ovirt/engine/core/services/GetAvailableConsoles.java
 
b/backend/manager/modules/services/src/main/java/org/ovirt/engine/core/services/GetAvailableConsoles.java
new file mode 100644
index 0000000..3a374b6
--- /dev/null
+++ 
b/backend/manager/modules/services/src/main/java/org/ovirt/engine/core/services/GetAvailableConsoles.java
@@ -0,0 +1,113 @@
+package org.ovirt.engine.core.services;
+
+import org.apache.commons.lang.StringUtils;
+import org.codehaus.jackson.map.ObjectMapper;
+import org.ovirt.engine.core.bll.interfaces.BackendInternal;
+import org.ovirt.engine.core.common.businessentities.VM;
+import org.ovirt.engine.core.common.queries.IdQueryParameters;
+import org.ovirt.engine.core.common.queries.VdcQueryReturnValue;
+import org.ovirt.engine.core.common.queries.VdcQueryType;
+import org.ovirt.engine.core.compat.Guid;
+import org.ovirt.engine.core.utils.ejb.BeanProxyType;
+import org.ovirt.engine.core.utils.ejb.BeanType;
+import org.ovirt.engine.core.utils.ejb.EjbUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.HttpURLConnection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class GetAvailableConsoles extends HttpServlet {
+    private static final Logger log = 
LoggerFactory.getLogger(GetAvailableConsoles.class);
+
+    private boolean runQuery(HttpServletRequest request, OutputStream out) {
+        BackendInternal backend = null;
+
+        String userGuidAsString = request.getParameter("user_guid");
+
+        Guid userGuid = null;
+
+        try {
+            if (StringUtils.isNotEmpty(userGuidAsString)) {
+                userGuid = Guid.createGuidFromString(userGuidAsString);
+            }
+        } catch (IllegalArgumentException e) {
+            log.debug("Could not read User GUID");
+        }
+
+        if (userGuid == null) {
+            return true;
+        }
+
+        try {
+            backend = (BackendInternal) EjbUtils.findBean(BeanType.BACKEND, 
BeanProxyType.LOCAL);
+            log.debug("Calling GetAllVmsForAnotherUser query");
+
+            IdQueryParameters userParam = new IdQueryParameters(userGuid);
+
+            VdcQueryReturnValue retVms = 
backend.runInternalQuery(VdcQueryType.GetAllVmsForAnotherUser, userParam);
+
+            if (retVms != null) {
+                List<VM> vmsList = retVms.getReturnValue();
+
+                ObjectMapper mapper = new ObjectMapper();
+
+                Map<String, String> jsonVms = new HashMap<String, String>();
+
+                for (VM vm : vmsList) {
+                    IdQueryParameters vmParam = new 
IdQueryParameters(vm.getId());
+
+                    VdcQueryReturnValue retAddr = 
backend.runInternalQuery(VdcQueryType.GetManagementInterfaceAddressByVmId, 
vmParam);
+
+                    if (retAddr != null && retAddr.getReturnValue() != null) {
+                        String vdsAddress = (String)retAddr.getReturnValue();
+
+                        jsonVms.put(vm.getName(), vdsAddress);
+                    }
+                }
+
+                mapper.writeValue(out, jsonVms);
+            } else {
+                log.error("Got NULL from backend.RunQuery!");
+            }
+        } catch (Throwable t) {
+            String msg = "Unable to contact Database!";
+            if (backend == null) {
+                msg = "Unable to contact Backend!";
+            }
+            log.error(msg, t);
+
+            return false;
+        }
+
+        return true;
+    }
+
+    protected void doGet(HttpServletRequest request, HttpServletResponse 
response)
+            throws ServletException, IOException {
+
+        response.setContentType("application/json");
+
+        OutputStream out = response.getOutputStream();
+
+        try {
+            if (!runQuery(request, out)) {
+                response.setStatus(HttpURLConnection.HTTP_INTERNAL_ERROR);
+                log.error("Failed to run GetConsolePublicKeys.");
+            }
+        } catch (Exception e) {
+            response.setStatus(HttpURLConnection.HTTP_INTERNAL_ERROR);
+            log.error("Error calling runQuery: ", e);
+        } finally {
+            out.close();
+        }
+    }
+}
diff --git 
a/backend/manager/modules/services/src/main/java/org/ovirt/engine/core/services/GetConsolePublicKeys.java
 
b/backend/manager/modules/services/src/main/java/org/ovirt/engine/core/services/GetConsolePublicKeys.java
new file mode 100644
index 0000000..3d8f309
--- /dev/null
+++ 
b/backend/manager/modules/services/src/main/java/org/ovirt/engine/core/services/GetConsolePublicKeys.java
@@ -0,0 +1,90 @@
+package org.ovirt.engine.core.services;
+
+import org.apache.commons.lang.StringUtils;
+import org.codehaus.jackson.map.ObjectMapper;
+import org.ovirt.engine.core.bll.interfaces.BackendInternal;
+import org.ovirt.engine.core.common.businessentities.aaa.DbUser;
+import org.ovirt.engine.core.common.queries.VdcQueryParametersBase;
+import org.ovirt.engine.core.common.queries.VdcQueryReturnValue;
+import org.ovirt.engine.core.common.queries.VdcQueryType;
+import org.ovirt.engine.core.utils.ejb.BeanProxyType;
+import org.ovirt.engine.core.utils.ejb.BeanType;
+import org.ovirt.engine.core.utils.ejb.EjbUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.HttpURLConnection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class GetConsolePublicKeys extends HttpServlet {
+    private static final Logger log = 
LoggerFactory.getLogger(GetConsolePublicKeys.class);
+
+    private boolean runQuery(HttpServletRequest request, OutputStream out) {
+        BackendInternal backend = null;
+
+        try {
+            backend = (BackendInternal) EjbUtils.findBean(BeanType.BACKEND, 
BeanProxyType.LOCAL);
+            log.debug("Calling GetAllDbUsers query");
+
+            VdcQueryParametersBase params = new VdcQueryParametersBase();
+
+            VdcQueryReturnValue v = 
backend.runInternalQuery(VdcQueryType.GetAllDbUsers, params);
+
+            if (v != null) {
+                List<DbUser> users = v.getReturnValue();
+
+                Map<String, String> jsonUsers = new HashMap<String, String>();
+
+                for (DbUser user : users) {
+                    if (StringUtils.isNotEmpty(user.getSshPublicKey())) {
+                        jsonUsers.put(user.getId().toString(), 
user.getSshPublicKey());
+                    }
+                }
+
+                ObjectMapper mapper = new ObjectMapper();
+
+                mapper.writeValue(out, jsonUsers);
+            } else {
+                log.error("Got NULL from backend.RunQuery!");
+            }
+        } catch (Throwable t) {
+            String msg = "Unable to contact Database!";
+            if (backend == null) {
+                msg = "Unable to contact Backend!";
+            }
+            log.error(msg, t);
+
+            return false;
+        }
+
+        return true;
+    }
+
+    protected void doGet(HttpServletRequest request, HttpServletResponse 
response)
+            throws ServletException, IOException {
+
+        response.setContentType("application/json");
+
+        OutputStream out = response.getOutputStream();
+
+        try {
+            if (!runQuery(request, out)) {
+                response.setStatus(HttpURLConnection.HTTP_INTERNAL_ERROR);
+                log.error("Failed to run GetConsolePublicKeys.");
+            }
+        } catch (Exception e) {
+            response.setStatus(HttpURLConnection.HTTP_INTERNAL_ERROR);
+            log.error("Error calling runQuery: ", e);
+        } finally {
+            out.close();
+        }
+    }
+}
diff --git 
a/backend/manager/modules/services/src/main/java/org/ovirt/engine/core/services/auth/ConsoleProxyLoginModule.java
 
b/backend/manager/modules/services/src/main/java/org/ovirt/engine/core/services/auth/ConsoleProxyLoginModule.java
new file mode 100644
index 0000000..5c69a60
--- /dev/null
+++ 
b/backend/manager/modules/services/src/main/java/org/ovirt/engine/core/services/auth/ConsoleProxyLoginModule.java
@@ -0,0 +1,57 @@
+package org.ovirt.engine.core.services.auth;
+
+import java.security.acl.Group;
+import java.util.Map;
+import javax.security.auth.Subject;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.login.LoginException;
+
+import org.jboss.security.SimpleGroup;
+import org.jboss.security.SimplePrincipal;
+import org.jboss.security.auth.spi.UsernamePasswordLoginModule;
+
+import org.ovirt.engine.core.bll.interfaces.BackendInternal;
+import org.ovirt.engine.core.common.queries.ConfigurationValues;
+import org.ovirt.engine.core.common.queries.GetConfigurationValueParameters;
+import org.ovirt.engine.core.common.queries.VdcQueryReturnValue;
+import org.ovirt.engine.core.common.queries.VdcQueryType;
+
+import org.ovirt.engine.core.utils.ejb.BeanProxyType;
+import org.ovirt.engine.core.utils.ejb.BeanType;
+import org.ovirt.engine.core.utils.ejb.EjbUtils;
+
+public class ConsoleProxyLoginModule extends UsernamePasswordLoginModule {
+    @SuppressWarnings("rawtypes")
+    public void initialize(Subject subject, CallbackHandler callbackHandler,
+                           Map sharedState,
+                           Map options) {
+        super.initialize(subject, callbackHandler, sharedState, options);
+    }
+
+    @Override
+    protected String getUsersPassword() throws LoginException {
+
+        if (!getUsername().equals("consoleproxy")) {
+            throw new LoginException("Invalid user");
+        }
+
+        BackendInternal backend = (BackendInternal) 
EjbUtils.findBean(BeanType.BACKEND, BeanProxyType.LOCAL);
+
+        GetConfigurationValueParameters params = new 
GetConfigurationValueParameters(ConfigurationValues.ConsoleProxyPassword);
+
+        VdcQueryReturnValue v = 
backend.runInternalQuery(VdcQueryType.GetConfigurationValue, params);
+
+        return v.getReturnValue();
+    }
+
+    @Override
+    protected Group[] getRoleSets() throws LoginException {
+        SimpleGroup group = new SimpleGroup("Roles");
+        try {
+            group.addMember(new SimplePrincipal("console_proxy_role"));
+        } catch (Exception e) {
+            throw new LoginException("Failed to create group member for " + 
group);
+        }
+        return new Group[] { group };
+    }
+}
diff --git 
a/backend/manager/modules/services/src/main/webapp/WEB-INF/jboss-web.xml 
b/backend/manager/modules/services/src/main/webapp/WEB-INF/jboss-web.xml
new file mode 100644
index 0000000..29900ed
--- /dev/null
+++ b/backend/manager/modules/services/src/main/webapp/WEB-INF/jboss-web.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<jboss-web>
+    <security-domain>console-proxy-auth</security-domain>
+    <disable-audit>true</disable-audit>
+</jboss-web>
diff --git a/backend/manager/modules/services/src/main/webapp/WEB-INF/web.xml 
b/backend/manager/modules/services/src/main/webapp/WEB-INF/web.xml
index 97f27b4..a0a9cd0 100644
--- a/backend/manager/modules/services/src/main/webapp/WEB-INF/web.xml
+++ b/backend/manager/modules/services/src/main/webapp/WEB-INF/web.xml
@@ -131,6 +131,24 @@
     <url-pattern>/health/*</url-pattern>
   </servlet-mapping>
 
+  <servlet>
+      <servlet-name>availableconsoles</servlet-name>
+      
<servlet-class>org.ovirt.engine.core.services.GetAvailableConsoles</servlet-class>
+  </servlet>
+  <servlet-mapping>
+      <servlet-name>availableconsoles</servlet-name>
+      <url-pattern>/availableconsoles/*</url-pattern>
+  </servlet-mapping>
+
+  <servlet>
+      <servlet-name>publickeys</servlet-name>
+      
<servlet-class>org.ovirt.engine.core.services.GetConsolePublicKeys</servlet-class>
+  </servlet>
+  <servlet-mapping>
+      <servlet-name>publickeys</servlet-name>
+      <url-pattern>/publickeys/*</url-pattern>
+  </servlet-mapping>
+
   <!-- PageNotFoundForward Servlet -->
   <servlet>
       <servlet-name>PageNotFoundForwardServlet</servlet-name>
@@ -189,4 +207,27 @@
     </cookie-config>
   </session-config>
 
+    <security-constraint>
+        <web-resource-collection>
+            <web-resource-name>Console proxy</web-resource-name>
+            <url-pattern>/availableconsoles/*</url-pattern>
+            <url-pattern>/publickeys/*</url-pattern>
+        </web-resource-collection>
+        <auth-constraint>
+            <role-name>console_proxy_role</role-name>
+        </auth-constraint>
+    </security-constraint>
+
+  <login-config>
+      <auth-method>BASIC</auth-method>
+      <realm-name>Console proxy services</realm-name>
+  </login-config>
+
+  <security-role>
+      <description>
+          The role used to supply information to the console proxy
+      </description>
+      <role-name>console_proxy_role</role-name>
+  </security-role>
+
 </web-app>
diff --git a/packaging/dbscripts/upgrade/pre_upgrade/0000_config.sql 
b/packaging/dbscripts/upgrade/pre_upgrade/0000_config.sql
index d1e864f..1ed4713 100644
--- a/packaging/dbscripts/upgrade/pre_upgrade/0000_config.sql
+++ b/packaging/dbscripts/upgrade/pre_upgrade/0000_config.sql
@@ -655,6 +655,8 @@
 select fn_db_add_config_value('DefaultAutoConvergence','false','general');
 select fn_db_add_config_value('DefaultMigrationCompression','false','general');
 
+select fn_db_add_config_value('ConsoleProxyPassword','','general');
+
 
------------------------------------------------------------------------------------
 --                  Update with override section
 
------------------------------------------------------------------------------------
diff --git a/packaging/services/ovirt-engine/ovirt-engine.xml.in 
b/packaging/services/ovirt-engine/ovirt-engine.xml.in
index 3dbb8f3..7cfe127 100644
--- a/packaging/services/ovirt-engine/ovirt-engine.xml.in
+++ b/packaging/services/ovirt-engine/ovirt-engine.xml.in
@@ -301,6 +301,12 @@
           </authentication>
         </security-domain>
 
+        <security-domain name="console-proxy-auth" cache-type="default">
+          <authentication>
+            <login-module 
code="org.ovirt.engine.core.services.auth.ConsoleProxyLoginModule" 
flag="required"/>
+          </authentication>
+        </security-domain>
+
       </security-domains>
     </subsystem>
 


-- 
To view, visit http://gerrit.ovirt.org/35887
To unsubscribe, visit http://gerrit.ovirt.org/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I53c721da21cefcf4069d14c7016b6f7d97f9eac9
Gerrit-PatchSet: 1
Gerrit-Project: ovirt-engine
Gerrit-Branch: master
Gerrit-Owner: Vitor de Lima <vdel...@redhat.com>
_______________________________________________
Engine-patches mailing list
Engine-patches@ovirt.org
http://lists.ovirt.org/mailman/listinfo/engine-patches

Reply via email to