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